#define FUSE_USE_VERSION 26
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <unicode/utypes.h>
#include <unicode/ustring.h>
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include "utils.h"
#include "fuse.h"
#include "unistd.h"
#include "list.h"
#include <unicode/utf16.h>


#include <ctype.h>



#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/un.h> 
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>

#include "configuracion.h"

#define FAT                             	0
#define ULTIMO_FAT                          1
#define BOOT                            	2
#define RTA_BOOT                           	3
#define HSOK	     			101
#define HSFAIL	     			102

// #define READ_SECTOR_REQUEST 100
// #define WRITE_SECTOR_REQUEST 99
// #define RTA_WRITE_SECTOR_REQUEST 98
#define READ_SECTOR_REQUEST_LAST 97
#define SET_SECTORES_LAST 96

#define READ_SECTOR_REQUEST 			200
#define WRITE_SECTOR_REQUEST 			201
#define RTA_READ_SECTOR_REQUEST 		300
#define RTA_WRITE_SECTOR_REQUEST 		301

#define HANDSHAKE 	10

#define		SET_SECTORES		73
#define		RTA_SET_SECTORES	74
#define NUMEROPEDIDO			70



typedef struct Informacion_IPC
{
	long payLoadLength;
	short payLoadDescriptor;
	char descriptorID[16];
	void *payload;
} __attribute__ ((__packed__)) InfoIPC;

int generarStructIPC(char *payload, short mode, InfoIPC *rInfoIPC)  /*sort es 2 bytes,int es 4 bytes,uso short porq no es necesario usar mas en este caso*/
{	
	char *descriptor = (char *) malloc(sizeof(char) * 16);
	GenerarDescriptor(&descriptor);
	memset(rInfoIPC->descriptorID, '\0', 16);
	memcpy(rInfoIPC->descriptorID,descriptor,15); /*creo el descriptor y lo cargo en la estructura. */
	rInfoIPC->payLoadDescriptor=mode; /*cargo el protocolo a la struct*/		
	
	free(descriptor);
	
	if(payload!=NULL){
		rInfoIPC->payload = (char*) malloc(rInfoIPC->payLoadLength);
		memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,payload,rInfoIPC->payLoadLength); 
	}
	else{
		rInfoIPC->payload = (char*) malloc(5);
		memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,"nada",rInfoIPC->payLoadLength); 	
	}	
	
	return 0; 
}


int GenerarDescriptor(char **aux_descriptor){

	char descriptor[16];
	
	char cadena [] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int pos = 0;

 
	memset(descriptor, '\0', 16);

	for(pos = 0; pos < 15; descriptor[pos++] = cadena[(int)(rand()%62)]);
	descriptor[pos] = '\0';

    
	memcpy(*aux_descriptor, descriptor, 16);
	
	return 1;
}


int enviarIPC(int sock, InfoIPC *rInfoIPC)
{
	int tm;
	char *buffer;
	int bufLen;
	int length;

	bufLen = (sizeof(char) * strlen(rInfoIPC->descriptorID)) + sizeof(short) + sizeof(long) + sizeof(char)*rInfoIPC->payLoadLength + 20; /*Ese 20 no se de donde sale pero por las dudas lo dejo*/
	
	buffer	= (char*)malloc(bufLen);
	length =0;
	memcpy (buffer,&(rInfoIPC->payLoadLength),sizeof(long));
	length = sizeof(long);
	memcpy(buffer + length, &(rInfoIPC->payLoadDescriptor), sizeof(short));
	length += sizeof(short);
	memcpy(buffer + length, rInfoIPC->descriptorID, strlen(rInfoIPC->descriptorID)+1);
	length += strlen(rInfoIPC->descriptorID)+1;
	memcpy(buffer + length, rInfoIPC->payload, rInfoIPC->payLoadLength);
	length +=  rInfoIPC->payLoadLength; 
	
	tm = send(sock,buffer,length,0);
 	free(buffer);
	return tm;
}


int recibirIPC(int sock, InfoIPC* rInfoIPC)
{
	int length;
	int len;
	char* buffer;
	char* payload;
	int ret;

	len = sizeof(short) + sizeof(long) + 16; /*tamaño del header, sin payload.*/

	buffer	= (char*) malloc(len);

	ret = recv(sock, buffer, len, 0);
	rInfoIPC->payLoadLength = 0;
	if(ret == len)
	{   
		length  = 0;
		rInfoIPC->payLoadLength =  *((long *) buffer);
		length += sizeof(long);

		rInfoIPC->payLoadDescriptor = *((short*) (buffer + length));
		length += sizeof(short);

		strncpy(rInfoIPC->descriptorID,(char*)( buffer + length),16);
		length += 16;
		
 		free(buffer);
	}
        else 
        {
                free(buffer);
                return -1; /*retorno NOSERECIBIOLACANTDEDATOSAPROPIADA*/
	}

	if(rInfoIPC->payLoadLength != 0)
	{
     
         payload	= (char*)malloc(sizeof(char) * rInfoIPC->payLoadLength);
     		
      /*recibirDatos(sock, payload, rInfoIPC->payLoadLength);*/
      ret = recv(sock, payload,  rInfoIPC->payLoadLength, 0);   /*fuerzo a recibir dos veces para que en la segunda reciba los datos(pero es un solo send del otro lado)*/	
  
         rInfoIPC->payload 	= (char*)malloc(sizeof(char) * rInfoIPC->payLoadLength);
     	
      memset(rInfoIPC->payload,'\0',rInfoIPC->payLoadLength);
		memcpy(rInfoIPC->payload,payload,rInfoIPC->payLoadLength);
		
 		free(payload);
		return 0;  /*retorno OK*/

	   }
	   else
	   {
 		free(payload);
		 return HANDSHAKE;	
	    }
}	


int Conectar2 ( int iDescriptor_del_socket , char* sIP_remoto , int iPuerto_remoto_para_el_socket )
{
	struct sockaddr_in Str_sockaddr_in_paraConnect;/*estructura para el Connect*/

	Str_sockaddr_in_paraConnect.sin_family = AF_INET;/*estructura para el connect*/
	Str_sockaddr_in_paraConnect.sin_addr.s_addr = inet_addr (sIP_remoto);
	Str_sockaddr_in_paraConnect.sin_port = htons (iPuerto_remoto_para_el_socket);	
	memset (&(Str_sockaddr_in_paraConnect.sin_zero), 8, '\0');
	
	
	if ( connect ( iDescriptor_del_socket , (struct sockaddr *) & Str_sockaddr_in_paraConnect , sizeof (Str_sockaddr_in_paraConnect ) ) == -1 )/*conect & check*/
       {

		printf("error al conectar\n");

		return -1;
            }
	else
            {

		return 5;
            }
}

int crearSocket(int tipo){
	
    int sock;  
    
    switch(tipo){
    
	case AF_INET:
	
	    if((sock = socket(tipo,SOCK_STREAM,0)) == -1){   
		return -1; 
	    }
	
	    break;
	
	case AF_UNIX:
	    
	    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	    }  
	    
	    break;    
    }
    
    return sock;    
}

typedef struct BootRegion
{
    unsigned int bytes_per_sector;
    unsigned int sectors_per_cluster;	
    unsigned int count_sect_reservados;
    unsigned int num_fats;
    unsigned int total_sectors;
    unsigned int fat32_size;
    unsigned int first_data_sector;
    unsigned int cluster_size;
    unsigned int first_data_cluster;
    unsigned int count_clusters_fat;
} bootRegion;

//typedef char* sector;

typedef struct Sector
{
    char *sec;
}sector;

typedef struct Sectors
{
    sector *data;
    struct Sectors *sgt;
}sectors;

typedef u_int32_t clusterId;

typedef struct ClusterIds
{
  clusterId *data;
  struct ClusterIds *sgt;
}clusterIds;

typedef sectors cluster;  

typedef struct Clusters
{
  cluster *data;
  struct Clusters *sgt;
}clusters;


typedef unsigned int fatRegistry;


typedef struct CacheFatRegistry
{
   unsigned int pos;
   fatRegistry data;
}cacheFatRegistry;


typedef struct CacheFatRegistries
{
  cacheFatRegistry *data;
  struct CacheFatRegistries *sgt;
}cacheFatRegistries;


typedef unsigned int directoryType;

typedef struct DirectoryInput
{
    char longName[14];
    clusterId idCluster;
    char name[9];
    directoryType type;
    char ext[4];
    unsigned int size;
    pthread_mutex_t dir_mutex;
}__attribute__ ((packed)) directoryInput;

typedef struct DirectoryInputs
{
  directoryInput *data;
  //struct DirectoryInputs *content;
  struct DirectoryInputs *sgt;
}directoryInputs;

enum cluster_state {free_cluster, reserved, used, bad, last, error};


typedef struct Directory
{
  directoryInput *data;
  struct Directory *content;
  struct Directory *sgt;
}directory;


typedef struct CacheCluster {
//   char *file_path;
  unsigned int cluster_num;
  cluster *cluster_data;
  unsigned int wrote;
}cacheCluster;


typedef struct CacheClusters
{
  cacheCluster *data;
  struct CacheClusters *ant;
  struct CacheClusters *sgt;
}cacheClusters;



typedef struct CacheFile {
  char *path;
  unsigned int cant_opens;
//   sem_t write_semaphore;
  pthread_mutex_t write_mutex;
  unsigned int wrote;
  unsigned int change_size;
  unsigned int release_size;
  cacheClusters *cache_first;
  cacheClusters *cache_last;
}cacheFile;


typedef struct CacheFiles
{
  cacheFile *data;
  struct CacheFiles *sgt;
}cacheFiles;


typedef struct {
  uint8_t name[8];
  uint8_t ext[3];
  uint8_t type;
  uint64_t ocho_ceros;
  uint16_t high_first_cluster;
  uint32_t cuatro_ceros;
  uint16_t low_first_cluster;
  uint32_t size;
} __attribute__ ((packed)) directoryInputRegistry;


typedef struct NipcCluster{
    unsigned int sector_num;
    unsigned int offset;
    unsigned int size;
    int sock_desc;
    int wrote;
    char data[512];
}nipcCluster;


typedef struct ReadNipcSector{
    unsigned int sector_num;
    unsigned int size;
    sector *sec_data;
}readNipcSector;

typedef struct ReadNipcSectors
{
  readNipcSector *data;
  struct ReadNipcSectors *sgt;
}readNipcSectors;


// int readBootRegion(FILE* disk, bootRegion **boot);
int readBootRegion(FILE* disk, bootRegion *boot);
int readBootRegionField(FILE* disk, unsigned int *leer, unsigned int offset, unsigned int size, char *aux_data);
int loadFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable);
int loadSectorIntoFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado);

int readSector(FILE* disk, bootRegion* boot, unsigned int num_sector, unsigned int offset, unsigned int size, char** data_sector);
int readAllSector(FILE* disk, bootRegion *boot, char **data_sector, sectors *listSectors);
int loadFreeClusters(bootRegion *boot, fatRegistry *fatTable, char *freeClusters);
int addFreeClusters( char* freeClusters, clusterIds* listToAdd);
int deleteFreeClusters( char* freeClusters, clusterIds* listToDelete);
int readCluster(FILE* disk, bootRegion *boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors *listSectors);
int addDirectoryInputsFromSector(bootRegion *boot, char *data_sector, directoryInputs *dirs);
int addDirectoryInputsFromCluster(bootRegion *boot, cluster *dirCluster, directoryInputs *dirs);
int addDirectoryInputsFromLinkedClusters(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directoryInputs *dirs);
int addDirectoryContent(directory *direct, directoryInputs *dirs);
int addDirectory(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directory *direct);
int addDirectoryTree(FILE* disk, bootRegion *boot, fatRegistry *fatTable, unsigned int cluster_num, directory *direct, int level);

//int searchDirectory(directory *dir, char* name,directory *result);
//int cutPath(const char *path,char *directory[]);

int readFileFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, const char* path, unsigned int cluster_num, unsigned int offset, unsigned int size, char** content, unsigned int *newSize);
int writeSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector);
int writeCluster(FILE* disk, bootRegion *boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors *listSectors);
// int getFileSize(FILE* disk, bootRegion *boot, fatRegistry *fatTable, const char *path, unsigned int cluster_num, int *size);
int truncateCluster(sectors **listSectors, int offset);
int truncateSector(char **data_sector, int offset);
int increaseCluster(sectors *listSectors, int offset, int final_byte);
int increaseSector(char **data_sector, int offset, int final_byte);
int getClusterState(fatRegistry* fatTable, unsigned int cluster_num, enum cluster_state *state, unsigned int *cluster_registry);
int saveFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable);
int writeSectorFromFAT(FILE* disk, bootRegion* boot, unsigned int num_sector, fatRegistry* fatTable, unsigned int last_loaded, int iSocketConectado);
int setFreeCluster(char* freeClusters, unsigned int cluster_num);
int getFreeCluster(char* freeClusters, unsigned int *cluster_num);
int setUsedCluster(char *freeClusters, unsigned int content, unsigned int cluster_num);
int fillWithChar(char **string, char fill_char, int total_size);
int writeFileFromLinkedClusters(FILE *disk, bootRegion *boot, const char *path, fatRegistry *fatTable, unsigned int cluster_num, unsigned int old_size, unsigned int offset, unsigned int size, const char *content, unsigned int *wrote);
int charToListSectors(char *buf, unsigned int old_size, int cluster_of_file, unsigned int offset, unsigned int size, sectors **listSectors);
int createNullCluster(sectors **listSectors);
int createDirectoryInput(char **data_dir32, directoryInput *dir);
int createLongNameInput(char **data_dir32, directoryInput *dir);
int saveDirectoryInputIntoLinkedClusters(unsigned int cluster_num, char *new_dir_input, unsigned int mode);
int saveDirectoryInputIntoCluster(cluster *dirCluster, char *new_dir_input, unsigned int mode);
int saveDirectoryInputIntoSector(char **data_sector, char *new_dir_input, unsigned int mode);

char* rtrimHOTFAT(char* string, char junk);
char* ltrimHOTFAT(char *string, char junk);
int cutPath2(const char *path,char *directory,char* finalPath);
int newName(const char* path, char *name);
int fatherName(const char *path,char *fatherPath);
int searchPath(directory *dir, char* name, directory **result);
int searchPath2(directory *dir, char* name, directory **result, directory **last);
int searchDirectory(const char *path,directory *root, directory **dir);
int getDirectory(const char* path, directory *root, directory **dir);


int readSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector, int iSocketConectado);
int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector, int iSocketConectado);

int fsinfo();
int finfo(const char *path);
void intacad ( int n , char* cadena);
static void * console_run(void *param);

// ********** CACHE **********
int loadCacheFAT(FILE* disk, bootRegion *boot, cacheFatRegistries *cacheFatTable, unsigned int initial_sector, unsigned int final_sector);
int loadSectorIntoCacheFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, cacheFatRegistries *cacheFatTable, unsigned int index);

int createCacheFile(const char *path, int fi_flags);
int releaseCacheFile(const char* path, int fi_flags);
int releaseCacheData(cacheFile *file);

int readClusterFromCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);
int writeClusterIntoCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);

int readCacheCluster(cluster *cluster_data, unsigned int offset, unsigned int size, sectors* listSectors);
int writeCacheCluster(cluster **cluster_data, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors);


int writeSector3(int numero, sectors *listSectors);
int readSector3(int numero, sectors *listSectors);

int flushCache(const char *path);

void cacheDump(int signal);
int cantClustersCache(cacheClusters *pNodo);

// ********** FUSE_FUNCTIONS **********
static void * hotfat_fuse_main(void*);
int hotfat_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int hotfat_open(const char *path, struct fuse_file_info *fi);
int hotfat_getattr(const char *path, struct stat *stbuf);
int hotfat_rename(const char *path, const char *newpath);
int hotfat_truncate(const char *path, off_t offset);
int hotfat_create(const char *path, mode_t mode, struct fuse_file_info *fi);
// int hotfat_mknod(const char *path, mode_t mode , dev_t dev); 
void hotfat_fullpath(char fpath[256], const char *path);
int hotfat_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int hotfat_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi);
int hotfat_flush(const char *path, struct fuse_file_info *fi);
int hotfat_release(const char *path, struct fuse_file_info *fi);
int hotfat_mkdir(const char *path, mode_t mode); 
int hotfat_rmdir(const char* path);
int hotfat_unlink(const char *path);

int youMakeMeFiller(directory *dir,void *buf,fuse_fill_dir_t *filler);
int getAttrOfDir(directory *dir, const char *path,struct stat *stbuf);

struct fuse_operations x;

struct bb_state {
    FILE *logfile;
    char *rootdir;
};

directory *root = NULL;
bootRegion *boot;
FILE *disk;
fatRegistry *fatTablePointer;
char *freeClusters;

unsigned int cache_size;
// cacheCluster *cache;
unsigned int cant_cache_clusters;
unsigned int cache_enabled;

cacheFiles *fileDescriptorsTable;
u_int8_t *modifyPointer;

char *ipDisco;
int puertoDisco;
char *pathMontaje;

int clusters_loaded_FAT;

pthread_mutex_t mutex_descriptors_table;

int main(int argc, char *argv[])
{
    int i;
    pthread_t consoleThreadID;
    
    pthread_mutex_init(&mutex_descriptors_table, NULL);
    clusters_loaded_FAT = 0;
    
    cargarConfig();
    
    ipDisco = (char *) malloc (sizeof(char) * 16);
    strcpy(ipDisco, obtenerValor("ipDisco"));//(char *)"192.168.240.128");
    puertoDisco = atoi(obtenerValor("puertoDisco"));//8010;
    cache_size = atoi(obtenerValor("cacheSize"));//32768;
    
    pathMontaje = (char *) malloc (sizeof(char) * 256);
    strcpy(pathMontaje , obtenerValor("pathMontaje"));//"../Disco");
    
    printf("\n------- HOTFAT's FILE SYSTEM --------\n");
    printf("----------- Configuration -----------\n");
    printf("- ipDisco: %s\n", ipDisco);
    printf("- puertoDisco: %i\n", puertoDisco);
    printf("- cacheSize: %i\n", cache_size);
    printf("-------------------------------------\n\n");
    
    x.readdir = hotfat_readdir;
    x.open = hotfat_open;
    x.getattr = hotfat_getattr;
    x.read = hotfat_read;
    x.rename = hotfat_rename;
    x.truncate = hotfat_truncate;
    x.create = hotfat_create;
    x.write = hotfat_write;
    x.flush = hotfat_flush;
    x.release = hotfat_release;
    x.mkdir = hotfat_mkdir;
    x.rmdir = hotfat_rmdir;
    x.unlink = hotfat_unlink;
    

    boot = (bootRegion *) malloc (sizeof(bootRegion));

    disk = fopen("../fat32_legui.disk", "r+");
    
    readBootRegion(disk, boot);
        
    printf("bytes_per_sector: %i\n", boot->bytes_per_sector);
    printf("sectors_per_cluster: %i\n", boot->sectors_per_cluster);
    printf("count_sect_reservados: %i\n", boot->count_sect_reservados);
    printf("count_fats: %i\n", boot->num_fats);
    printf("total_sectors: %i\n", boot->total_sectors);
    printf("fat32_size: %i\n", boot->fat32_size);
    printf("cluster_size: %i\n", boot->cluster_size);
    printf("First_data_sector: %i\nNro Byte: %i\n", boot->first_data_sector, boot->first_data_sector * boot->bytes_per_sector);
    printf("First_data_cluster: %i\n", boot->first_data_cluster);
    
    
    fatRegistry fatTable[boot->count_clusters_fat];
    uint8_t modify[boot->count_clusters_fat];

    
    loadFAT(disk, boot, fatTable);
    
    printf("FatTable: \n");
    for(i=0;i<clusters_loaded_FAT;i++)
	if(fatTable[i]!=0)
	    printf("%u %x\n",i,fatTable[i]);

	    
    int m;
    for(m=0;m<boot->count_clusters_fat;m++)
	modify[m]=0;
    
    modifyPointer = modify;
	    
    fatTablePointer = fatTable;
    freeClusters = (char *) malloc (sizeof(char) * boot->count_clusters_fat);
    loadFreeClusters(boot, fatTable, freeClusters);

    
    root = (directory *) malloc (sizeof(directory));
    
    root->data = (directoryInput *) malloc (sizeof(directoryInput));
    strcpy(root->data->longName, "/");
    strcpy(root->data->name, "root");
    strcpy(root->data->ext, "");
    root->data->idCluster = 2;
    root->data->type = 16;
    root->data->size = 0;
    root->content = NULL;
    root->sgt = NULL;
    pthread_mutex_init(&(root->data->dir_mutex), NULL);

    
    addDirectoryTree(disk, boot, fatTable, root->data->idCluster, root, -1);
    
    cant_cache_clusters = cache_size / boot->cluster_size;
    if(cant_cache_clusters > 0)
    {	
// 	cache = (cacheCluster *) malloc (cant_cache_clusters * sizeof(cacheCluster));
// 	for(i=0;i<cant_cache_clusters;i++)
// 	{
// 	    cache[i].cluster_data = (cluster *) malloc (sizeof(cluster));
// 	    cache[i].cluster_data->data = NULL;
// 	    cache[i].cluster_data->sgt = NULL;
// 	    cache[i].file_path = (char *) malloc (sizeof(char) * 50);
// 	}
	cache_enabled = 1;
	//system("handle SIGUSR1 ignore");
    }
    else
	cache_enabled = 0;
    
    
	signal(SIGUSR1, cacheDump);
    
    fileDescriptorsTable = (cacheFiles *) malloc(sizeof(cacheFiles));
    fileDescriptorsTable->data = NULL;
    fileDescriptorsTable->sgt = NULL;

    
//     if(pthread_create(&consoleThreadID, NULL, console_run, NULL) != 0)
//     {
// 	printf("\nError al crear el hilo");
//     }    
    
    
    void *param = NULL;
    hotfat_fuse_main(param);

//     pthread_exit(&consoleThreadID);
	
    free(ipDisco);
//     if(cache_enabled == 1)
//     {	
// 	for(i=0;i<cant_cache_clusters;i++)
// 	{
// 	    free(cache[i].cluster_data->data);
// 	    free(cache[i].cluster_data);
// 	    free(cache[i].file_path);
// 	}
// 	free(cache);
//     }

	free(freeClusters);

    directory *qdir;
    while(root->content != NULL)
    {
	qdir = root->content;
	root->content = root->content->sgt;
// 	free(qdir->data->name);
// 	free(qdir->data->ext);
	free(qdir->data);
	free(qdir);
    }
//     free(root->data->name);
    free(root->data);
    free(root);
    
    free(boot);
    free(fileDescriptorsTable);
    fclose(disk);
    
    printf("Terminamos\n");
    
    return 1;
}


static void * hotfat_fuse_main(void *param)
{
    struct bb_state *bb_data;
    
    bb_data = (struct bb_state *) malloc(sizeof(struct bb_state));
    bb_data->rootdir = (char *) malloc(sizeof(char) * 256);//sizeof(char));
    bb_data->rootdir = realpath(pathMontaje, NULL);
    
    
    int argc2 = 2;
    char *argv2[] = { "/home/utn_so/fat32_legui.disk" , pathMontaje , "-d"};

    fuse_main(3,argv2,&x,bb_data);
    
    free(bb_data->rootdir);
    free(bb_data);
    
    return NULL;
}


int loadFreeClusters(bootRegion *boot, fatRegistry *fatTable, char *freeClusters)
{
    int i;
    
    for (i = 0;(i< (boot->fat32_size * boot->bytes_per_sector)/4) && (i<clusters_loaded_FAT);i++)
    {
	if(!(fatTable[i]))
	    freeClusters[i] = '0';
	else
	    freeClusters[i] = '1';
    }
    
    return 1;
}

int addFreeClusters(char *freeClusters, clusterIds *listToAdd)
{
    int i = 0;
    clusterIds *q = listToAdd;
    for(i=0;q!=NULL;i++)
    {
      clusterIds *aux = q->sgt;
      
      freeClusters[*(q->data)] = '0';
      q = aux;
    }
}

int deleteFreeClusters(char *freeClusters, clusterIds *listToDelete)
{
    int i = 0;
    clusterIds *q = listToDelete;
    for(i=0;q!=NULL;i++)
    {
      clusterIds *aux = q->sgt;
      freeClusters[*(q->data)] = '1';
      q = aux;
    }
}

int loadFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable)
{
    if(clusters_loaded_FAT < boot->count_clusters_fat)
    {
	unsigned int last_loaded, num_sector;
	int i;
	
	num_sector = boot->count_sect_reservados;// + 1;
	
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado, ipDisco, puertoDisco);	
	
	InfoIPC rInfoIPC;
	
	rInfoIPC.payLoadLength = 5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	
	enviarIPC(iSocketConectado,&rInfoIPC);
        free(rInfoIPC.payload);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
        free(rInfoIPC.payload);
	if(rInfoIPC.payLoadDescriptor == HSOK)
	{
	    
 	   last_loaded = 0;
 	   for (i = 0;i< boot->fat32_size;i++)
      {
        loadSectorIntoFAT(disk, boot, num_sector + i, fatTable, last_loaded, iSocketConectado);
        last_loaded += (boot->bytes_per_sector/4);
 	   }

	//    i = clusters_loaded_FAT / (boot->bytes_per_sector/4);
	//    loadSectorIntoFAT(disk, boot, num_sector + i, fatTable, clusters_loaded_FAT, iSocketConectado);
	//    clusters_loaded_FAT += (boot->bytes_per_sector/4);

      clusters_loaded_FAT = last_loaded;
	}
    
	close(iSocketConectado);
	
    }   
    return 1;
}


int loadSectorIntoFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado)
{
    int i,j;
    char *data_sector;
    data_sector = (char *) malloc(sizeof(char) * 512);
    
    readSectorFAT(disk, boot, num_sector, 0, boot->bytes_per_sector, &data_sector, iSocketConectado);
    
    for (i = 0,j=last_loaded;i< boot->bytes_per_sector;i+=4,j++)
    {
	memcpy(&fatTable[j],&data_sector[i],4);
    }
    
    free(data_sector);
    
    return 1;
}

int loadCacheFAT(FILE* disk, bootRegion* boot, cacheFatRegistries* cacheFatTable, unsigned int initial_sector, unsigned int final_sector)
{
    unsigned int index, num_sector;
    int i;
    
    num_sector = boot->count_sect_reservados + initial_sector;
    
    index = 0 + initial_sector * (boot->bytes_per_sector / 4);
    for (i = 0;(i < (final_sector - initial_sector)) && (i< boot->fat32_size) ;i++)
    {
	loadSectorIntoCacheFAT(disk, boot, num_sector + i, cacheFatTable, index);
	index += (boot->bytes_per_sector/4);
    }

    return 1;
}

int loadSectorIntoCacheFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, cacheFatRegistries *cacheFatTable, unsigned int index)
{
    int i,j;
    char *data_sector;
    data_sector = (char *) malloc(sizeof(char) * 512);
    
    readSector(disk, boot, num_sector, 0, boot->bytes_per_sector, &data_sector);
    
    for (i = 0,j=index;i< boot->bytes_per_sector;i+=4,j++)
    {
	cacheFatRegistry *aux_registry = (cacheFatRegistry *) malloc (sizeof(cacheFatRegistry));
	
	aux_registry->pos = j;
	memcpy(&(aux_registry->data),&data_sector[i],4);
	
	addToList((gl *)cacheFatTable, aux_registry);
	
	
    }
    
    free(data_sector);
    
    
    return 1;
}



// int readBootRegion(FILE* disk, bootRegion **boot)
int readBootRegion(FILE* disk, bootRegion *boot)
{
    
    char *aux_data = (char *) malloc(sizeof(char) * 512);
    readSector(disk, boot, 0, 0, 512, &aux_data);
    
    readBootRegionField(disk, &(boot->bytes_per_sector), (unsigned int)0x0B, 2, aux_data);
    readBootRegionField(disk, &(boot->sectors_per_cluster) , (unsigned int)0x0D, 1, aux_data);
    readBootRegionField(disk, &(boot->count_sect_reservados) , (unsigned int)0x0E, 2, aux_data);
    readBootRegionField(disk, &(boot->num_fats), (unsigned int)0x10, 1, aux_data);
    readBootRegionField(disk, &(boot->total_sectors) , (unsigned int)0x20, 4, aux_data);
    readBootRegionField(disk, &(boot->fat32_size), (unsigned int)36, 4, aux_data);
    
    boot->first_data_sector = boot->count_sect_reservados + (boot->num_fats * boot->fat32_size);
    
    boot->cluster_size = boot->bytes_per_sector * boot->sectors_per_cluster;
    boot->first_data_cluster = boot->first_data_sector / boot->sectors_per_cluster;
    
    boot->count_clusters_fat = (boot->fat32_size * boot->bytes_per_sector) / 4;
    
    free(aux_data);
    
    return 1;
}

int readBootRegionField(FILE* disk, unsigned int *leer, unsigned int offset, unsigned int size, char *aux_data)
{
    unsigned int *aux_leer;
    aux_leer = (unsigned int*) malloc(sizeof(unsigned int));
    memset(aux_leer, 0, sizeof(unsigned int));
    
    memcpy(aux_leer, aux_data + offset, size);
    
    *leer = aux_leer[0];
    return 1;
}


// int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
// 
//     
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
//     
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     while(i < div_sectors_int)
// 	i++;
//     
//     int iSocketConectado = crearSocket(AF_INET);
//     Conectar2(iSocketConectado, ipDisco, puertoDisco);	
//     
//     InfoIPC hsInfoIPC;
//     
//     hsInfoIPC.payLoadLength = 5;
//     generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
//     enviarIPC(iSocketConectado,&hsInfoIPC);
//     
//     recibirIPC(iSocketConectado,&hsInfoIPC);
//     if(hsInfoIPC.payLoadDescriptor == HSOK)
//     {
// 	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
// 	int cant = 0;
// 	while(i<boot->sectors_per_cluster && i<= div_total_size_int)
// 	{
// 	    if(i == div_total_size_int)
// 		aux_size = div_total_size_resto;
// 	    else
// 		aux_size = boot->bytes_per_sector;
// 	    
// 	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
// 	    cluster_data[cant].offset = div_sectors_resto;
// 	    cluster_data[cant].size = aux_size;
// 
// 	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
// 	    InfoIPC sInfoIPC;
// 	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
// 	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
// 	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
// 	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&sInfoIPC);
// 	    enviarIPC(iSocketConectado ,&sInfoIPC);
// 	    free(num_sector_str);
// 	    cant++;
// 	    
// 	    div_sectors_resto = 0;
// 	    i++;
// 	}
// 	
// 
// 	fd_set set_socket;
// 	FD_SET(iSocketConectado, &set_socket);
// 
// 	struct timeval timeout;
// 	int rv;
// 	
// 	timeout.tv_sec = 3;
// 	timeout.tv_usec = 0;
// 
// 	int j=0;
// 	int w=0;
// 	i=0;
// 	
// 	while(w < cant)
// 	{
// 	    FD_ZERO(&set_socket);
// 	    FD_SET(iSocketConectado, &set_socket);
// 	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, &timeout);
// 	    if(rv == -1)
// 	    {
// 		printf("Llamada del Select error\n");
// 		FD_CLR(iSocketConectado, &set_socket);
// 		free(cluster_data);
// 		return -1;
// 	    }
// 	    if(rv == 0)
// 		break;
// 
// 	    if(FD_ISSET(iSocketConectado, &set_socket))
// 	    {
// 		InfoIPC rInfoIPC;
// 		unsigned int nro_pedido, nro_sector;
// 		recibirIPC(iSocketConectado,&rInfoIPC);
// 		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
// 		{
// 		    nro_pedido = atoi(rInfoIPC.payload);
// 		
// 		    recibirIPC(iSocketConectado,&rInfoIPC);
// 		    if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
// 		    {
// 			nro_sector = atoi(rInfoIPC.payload);
// 			recibirIPC(iSocketConectado,&rInfoIPC);
// 			for(j=0;j<cant;j++)
// 			    if(cluster_data[j].sector_num == nro_sector)
// 			    {
// 				memcpy(cluster_data[j].data, rInfoIPC.payload, rInfoIPC.payLoadLength);
// 			    }
// 			w++;
// 		    }
// 		    else
// 		    {
// 			rv = 0;
// 			break;
// 		    }
// 		}
// 		else
// 		{
// 		    rv = 0;
// 		    break;
// 		}
// 	    }
// 	
// 	    FD_CLR(iSocketConectado, &set_socket);
// 	}
// 	
// 	close(iSocketConectado);
// 	    
// 	int retv = 0;
// 	if(w < cant && rv == 0)
// 	    retv = readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
// 	else
// 	{
// 	    for(i=0;i<cant;i++)
// 	    {
// 		sector *aux_sec = (sector *) malloc (sizeof(sector));
// 		aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
// 		memcpy(aux_sec->sec, cluster_data[i].data + cluster_data[i].offset, (cluster_data[i].size - cluster_data[i].offset));
// 		addToList((gl *)listSectors,aux_sec);
// 	    }
// 	}
// 	free(cluster_data);
//     }
//     else
//     {
// 	printf("Error al conectar\n");
// 	close(iSocketConectado);
// 	return -1;
//     }
// 
//     return 1;
// }

// int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
// 
//     
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
//     
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     while(i < div_sectors_int)
// 	i++;
//     
//     int iSocketConectado = crearSocket(AF_INET);
//     Conectar2(iSocketConectado, ipDisco, puertoDisco);	
//     
//     InfoIPC hsInfoIPC;
//     
//     hsInfoIPC.payLoadLength = 5;
//     generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
//     enviarIPC(iSocketConectado,&hsInfoIPC);
//     
//     recibirIPC(iSocketConectado,&hsInfoIPC);
//     if(hsInfoIPC.payLoadDescriptor == HSOK)
//     {
// 	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
// 	int cant = 0;
// 	while(i<boot->sectors_per_cluster && i<= div_total_size_int)
// 	{
// 	    if(i == div_total_size_int)
// 		aux_size = div_total_size_resto;
// 	    else
// 		aux_size = boot->bytes_per_sector;
// 	    
// 	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
// 	    cluster_data[cant].offset = div_sectors_resto;
// 	    cluster_data[cant].size = aux_size;
// 
// 	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
// 	    InfoIPC sInfoIPC;
// 	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
// 	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
// 	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
// 	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST_LAST,&sInfoIPC);
// 	    enviarIPC(iSocketConectado ,&sInfoIPC);
// 	    free(num_sector_str);
// 	    cant++;
// 	    
// 	    div_sectors_resto = 0;
// 	    i++;
// 	}
// 	
// 
// 	fd_set set_socket;
// // 	FD_SET(iSocketConectado, &set_socket);
// 
// 	struct timeval timeout;
// 	int rv;
// 	
// 	timeout.tv_sec = 3;
// 	timeout.tv_usec = 0;
// 
// 	int j=0;
// 	int w=0;
// 	i=0;
// 	
// 	while(w < cant)
// 	{
// 	    FD_ZERO(&set_socket);
// 	    FD_SET(iSocketConectado, &set_socket);
// 	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, NULL);
// 	    if(rv == -1)
// 	    {
// 		printf("Llamada del Select error\n");
// 		FD_CLR(iSocketConectado, &set_socket);
// 		free(cluster_data);
// 		return -1;
// 	    }
// 	    if(rv == 0)
// 		break;
// 
// 	    if(FD_ISSET(iSocketConectado, &set_socket))
// 	    {
// 		InfoIPC rInfoIPC;
// 		unsigned int nro_sector;
// // 		recibirIPC(iSocketConectado,&rInfoIPC);
// // 		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
// // 		{
// // 		    nro_pedido = atoi(rInfoIPC.payload);
// 		
// 		    recibirIPC(iSocketConectado,&rInfoIPC);
// 		    if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
// 		    {
// 			nro_sector = atoi(rInfoIPC.payload);
// 			
// 			InfoIPC rInfoIPC2;
// 			recibirIPC(iSocketConectado,&rInfoIPC2);
// 			for(j=0;j<cant;j++)
// 			    if(cluster_data[j].sector_num == nro_sector)
// 			    {
// 				memcpy(cluster_data[j].data, rInfoIPC2.payload, rInfoIPC2.payLoadLength);
// 				w++;
// 			    }
// 		    }
// 		    else
// 		    {
// 			rv = 0;
// 			break;
// 		    }
// // 		}
// // 		else
// // 		{
// // 		    rv = 0;
// // 		    break;
// // 		}
// 	    }
// 	
// 	    FD_CLR(iSocketConectado, &set_socket);
// 	}
// 	
// 	close(iSocketConectado);
// 	    
// 	int retv = 0;
// 	if(w < cant && rv == 0)
// 	{
// // 	    free(cluster_data);
// 	    retv = readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
// 	}
// 	else
// 	{
// 	    listSectors->data = NULL;
// 	    listSectors->sgt = NULL;
// 	    for(i=0;i<cant;i++)
// 	    {
// 		sector *aux_sec = (sector *) malloc (sizeof(sector));
// 		aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
// 		memcpy(aux_sec->sec, cluster_data[i].data + cluster_data[i].offset, (cluster_data[i].size - cluster_data[i].offset));
// 		addToList((gl *)listSectors,aux_sec);
// 	    }
// // 	    free(cluster_data);	
// 	}
//     }
//     else
//     {
// 	printf("Error al conectar\n");
// 	close(iSocketConectado);
// 	return -1;
//     }
// 
//     return 1;
// }

int readClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    unsigned int div_sectors_int=0, div_sectors_resto=0, div_total_size_int=0, div_total_size_resto=0, aux_size=0, i = 0;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    while(i < div_sectors_int)
	i++;
    
    readNipcSectors *listReadSectors = (readNipcSectors *) malloc (sizeof(readNipcSectors));
    listReadSectors->data = NULL;
    listReadSectors->sgt = NULL;
    
    char sContador[20];
//     int iSocketConectado;
    InfoIPC rInfoIPC;
    int contador=i;
    fd_set set_socketsHiloPrincipal;
    cliente *pNodoCliente,*pAuxCliente;
    int iMayorSocket=0;
    cliente* ListaClientes=NULL;
    cliente* ListaClientes_Ult=NULL;
    
    /*Creo 8 socketes y envio lecturas de 8 numeros*/
    int numero = num_cluster * boot->sectors_per_cluster;
    
    
    while(contador < boot->sectors_per_cluster)
    {   
	
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	/*HANDSHAKE*/ 	
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado,ipDisco,puertoDisco);	
	rInfoIPC.payLoadLength=5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
        free(rInfoIPC.payload);
	recibirIPC(iSocketConectado,&rInfoIPC);
        free(rInfoIPC.payload);
	
	if(rInfoIPC.payLoadDescriptor== HSOK)
	{
	    pNodoCliente = (cliente *)malloc(sizeof(cliente));
	    pNodoCliente->socketCliente=iSocketConectado;
	    pNodoCliente->offset = div_sectors_resto;
	    pNodoCliente->size = aux_size;
	    agregarAListaDeClientes(&pNodoCliente,&ListaClientes,&ListaClientes_Ult);
	    intacad((contador+numero),sContador);
	    rInfoIPC.payLoadLength=strlen(sContador)+1;
	    generarStructIPC(sContador,READ_SECTOR_REQUEST_LAST,&rInfoIPC);
	    enviarIPC(iSocketConectado,&rInfoIPC);
            free(rInfoIPC.payload);
	}	
	
	div_sectors_resto = 0;
	contador++;
    }
    
    /*Escucho respuestas en esos sockets*/
    
    while(ListaClientes!=NULL)
    {    
	FD_ZERO(&set_socketsHiloPrincipal);
	pAuxCliente = ListaClientes;
	while(pAuxCliente != NULL)
	{
	    FD_SET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal);	
	    if(pAuxCliente->socketCliente > iMayorSocket)
		iMayorSocket = pAuxCliente->socketCliente;
	    pAuxCliente = pAuxCliente->Sgt;
	}
	
	
	select(iMayorSocket + 1,&set_socketsHiloPrincipal, NULL, NULL,NULL);
	
	pAuxCliente = ListaClientes;
	while(pAuxCliente != NULL)
	{
	    if( FD_ISSET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal ) > 0 ){
		break;
	    }
	    pAuxCliente = pAuxCliente->Sgt;
	}
	if(pAuxCliente != NULL)
	{		
	    recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
// 	    printf("Sector: %s \n",(char *)rInfoIPC.payload);
	    
	    readNipcSector *aux_read_sector = (readNipcSector *) malloc (sizeof(readNipcSector));
	    aux_read_sector->sector_num = atoi((char *)rInfoIPC.payload);
            free(rInfoIPC.payload);
	    
	    recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
// 	    printf("Recibi datos: %s \n",(char *)rInfoIPC.payload);
	    
	    close(pAuxCliente->socketCliente);
	    FD_CLR(pAuxCliente->socketCliente, &set_socketsHiloPrincipal);
	    SacarDeLista_Clientes(&pAuxCliente,&ListaClientes,&ListaClientes_Ult);
	    
	    aux_read_sector->sec_data = (sector *) malloc (sizeof(sector));
	    aux_read_sector->sec_data->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
	    memcpy(aux_read_sector->sec_data->sec, rInfoIPC.payload + pAuxCliente->offset, pAuxCliente->size - pAuxCliente->offset);
	    aux_read_sector->size = pAuxCliente->size - pAuxCliente->offset;
            free(rInfoIPC.payload);
	    
	    addToList((gl *)listReadSectors, aux_read_sector);
	    
	    free(pAuxCliente);
	}
    }
    
    if(listReadSectors != NULL)
    {
	int ret = 0;
	while(ret == 0)
	    ret = ordenarLista(&listReadSectors);
	
	while(listReadSectors != NULL)
	{
	    sector *sec_data = (sector *) malloc (sizeof(sector));
	    sec_data->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
	    
	    memcpy(sec_data->sec, listReadSectors->data->sec_data->sec , listReadSectors->data->size );
	    
	    addToList((gl *)listSectors, sec_data);
	
	    
	    readNipcSector *aux2_read_sector;
	    aux2_read_sector = listReadSectors->data;
	    listReadSectors = listReadSectors->sgt;
	
	    free(aux2_read_sector->sec_data->sec);
	    free(aux2_read_sector->sec_data);
	    free(aux2_read_sector);
	}
    }


    return 1;
    
}

int readSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector)
{
    
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado, ipDisco, puertoDisco);	
	
	InfoIPC rInfoIPC;
	char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
	
	rInfoIPC.payLoadLength = 5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	
	enviarIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	if(rInfoIPC.payLoadDescriptor == HSOK)
	{
	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
	    InfoIPC sInfoIPC;
	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
	    sprintf(num_sector_str, "%u", num_sector);
	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST,&sInfoIPC);
	    enviarIPC(iSocketConectado ,&sInfoIPC);
	    free(num_sector_str);
	    free(sInfoIPC.payload);
	    
	    InfoIPC rInfoIPC;
	    unsigned int nro_pedido, nro_sector;
// 	    recibirIPC(iSocketConectado,&rInfoIPC);
// 	    if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
// 	    {
// 		nro_pedido = atoi(rInfoIPC.payload);
	    
		recibirIPC(iSocketConectado,&rInfoIPC);
		if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
		{
		    nro_sector = atoi(rInfoIPC.payload);
		    free(rInfoIPC.payload);
		    recibirIPC(iSocketConectado,&rInfoIPC);
		    memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
		    free(rInfoIPC.payload);
		}
		else
		    free(rInfoIPC.payload);
// 	    }
	}
// 	
	close(iSocketConectado);
	free(num_sector_str);
	
    return 1;
}


// int readSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector)
// {
//     char *aux_leer = NULL;
//     aux_leer = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
// //     char *aux_leer[512];
//     
// 
// //     /**CONNECT**/
// // //     t_socket_client *client = sockets_createClient("10.0.2.15",atoi("8000") + 1);
// //     t_socket_client* client = malloc( sizeof(t_socket_client) );
// //     client->socket = malloc( sizeof(t_socket) );
// //     client->socket->desc = socket(AF_INET, SOCK_STREAM, 0);
// //     sockets_setMode(client->socket, SOCKETMODE_BLOCK);
// //     
// //     if (client->socket == NULL){
// // 	    return NULL;
// //     }
// //     sockets_setState(client, SOCKETSTATE_DISCONNECTED);
// //     sockets_connect(client, ipDisco, 9012);
// //     
// //     /**Handshake**/
// //     t_nipc *nipc = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// //     nipc_setdata(nipc, (char *)strdup("PFS"), strlen("PFS") + 1);
// // 
// //     nipc_send(nipc, client);
// // 
// //     nipc_destroy(nipc);
// //     t_socket_buffer *buffer = (t_socket_buffer *)sockets_recv(client);
// //     nipc = (t_nipc *)nipc_deserializer(buffer, 0);
// //     printf("%s", nipc->payload);
// //     sockets_bufferDestroy(buffer);
// //     nipc_destroy(nipc);
//     
//     if (disk == NULL)
//     {
// 	printf("Error al leer el archivo\n");
// 	return 0;
//     }
//     else
//     {
// 	fseek(disk,(num_sector * boot->bytes_per_sector) + offset,SEEK_SET);
// 	fread(aux_leer, 1, (size - offset), disk);
// 
// // 	t_nipc *nipc2 = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// // 	nipc2->type = NIPC_READSECTOR_RQ;
// // 	char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
// // 	sprintf(num_sector_str, "%u", num_sector);
// // 	nipc_setdata(nipc2, num_sector_str, sizeof(char) * sizeof(unsigned int) + 1);
// // 	nipc_send(nipc2, client);
// // 	nipc_destroy(nipc2);
// // 	
// // 	t_nipc *nipc3 = (t_nipc *) nipc_create(NIPC_HANDSHAKE);
// // 	t_socket_buffer *buffer2 = (t_socket_buffer *)sockets_recv(client);
// // 	nipc3 = (t_nipc *)nipc_deserializer(buffer2, 0);
// // 	printf("%s", nipc3->payload);
// // 	memcpy(aux_leer, nipc3->payload + offset, (size - offset));
// // 	sockets_bufferDestroy(buffer2);
// // 	nipc_destroy(nipc3);
// 
//     }  
//     
//     
//     //*data_sector = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
//     *data_sector = aux_leer;
//     
//     
//     return 1;
// }

//Agregar o remover uno o varios clusters libre a una cadena de clusters, Se utiliza libreria generica de list.h
//agregar un cluster addToList(lista, cluster)
//agregar varios cluster addListToList(lista,listaDeCluster)
//eliminar un cluster deleteToList(lista, cluster)
//eliminar varios clusters deleteListToList(lista, listaDeCluster)

int readCluster(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sector *aux_sec = (sector *) malloc(sizeof(sector));
    aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    
    while(i < div_sectors_int)
	i++;
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
//     for(;i<boot->sectors_per_cluster;i++)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	readSector(disk, boot, i + (num_cluster * boot->sectors_per_cluster), div_sectors_resto, aux_size, &(aux_sec->sec));
	addToList((gl *)listSectors,aux_sec);
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
	div_sectors_resto = 0;
	i++;
    }
    
    free(aux_sec->sec);
    free(aux_sec);
    
    return 1;
}


int addDirectoryInputsFromSector(bootRegion *boot, char *data_sector, directoryInputs *dirs)
{
    int j,z;
    directoryInput *dir;// = (directoryInput *) malloc(sizeof(directoryInput));
    //char longName[26];
    int longName_flag = 0;
	char longName16[28];
	char longName8[14];
	
    for(j=0;j< boot->bytes_per_sector;j+=32)
    {
	
		if(data_sector[j] == 0)
		{
// 		    free(longName16);
// 		    free(longName8);
		    return 0;
		}
		if(data_sector[j] != '\345') //Ã¥ - 0xE5
		{
			dir = (directoryInput *) malloc(sizeof(directoryInput));
			//dir->name = (char *) malloc (sizeof(char) * 14);
			//dir->ext = (char *) malloc (sizeof(char) * 4);
			dir->idCluster = 0;
			dir->size = 0;
	// 		dir->longName = (char *) malloc(sizeof(char)*14);
		
			//char *aux_idCluster20 = (char *) malloc (sizeof(char));
			//char *aux_idCluster26 = (char *) malloc (sizeof(char));
			int aux_idCluster20 =0;
			int aux_idCluster21 =0;
			int aux_idCluster26 =0;
			int aux_idCluster27 =0;
			int aux_idSize28 =0;
			int aux_idSize29 =0;
			int aux_idSize30 =0;
			int aux_idSize31 =0;
			u_int32_t aux_idCluster = 0, aux_size = 0;
	
		    if (data_sector[j+11] == 0x0F)
		    {
// 		
 				
// 	// 		
// 	// // 		El utf16_str_len es el tamaÃ±o de la cadena en utf16. Un ej:
// 	// // 		char cadenaEnUTF16[] = { 'a', '\0', 'l', '\0', 'g', '\0', 'o', '\0', '\0', '\0' };
// 	// // 		int tamaÃ±oDeCadenaEnUTF16 = 10;
// 	// // 		char cadenaEnUTF8[tamaÃ±oDeCadenaEnUTF16/2];
// 	// // 		int tamaÃ±oDeCadenaEnUTF8 = 0;
// 	// // 		unicode_utf16_to_utf8_inbuffer(cadenaEnUTF16, tamaÃ±oDeCadenaEnUTF16, cadenaEnUTF8, &tamaÃ±oDeCadenaEnUTF8);
	 			int n = z;
				memset(longName16,'\0',28);
				memset(longName8,'\0',14);
				for(n=j;n<(32+j);n++)
				{
				    if((n-j) >= 1 && (n-j) < 11)
// 					memcpy(&(longName16)[n-j-1], &((data_sector)[n]), 1); 
					longName16[n-j-1] = data_sector[n];
				    if((n-j) >= 14 && (n-j) < 26)
// 					memcpy(&(longName16)[n-j-14+10], &((data_sector)[n]), 1);  
					longName16[n-j-14+10] = data_sector[n];
				    if((n-j) >= 28 && (n-j) < 32)
// 					memcpy(&(longName16)[n-j-28+22], &((data_sector)[n]), 1);  
					longName16[n-j-28+22] = data_sector[n];
				}
			
			
				
				int lenUTF16 = 26;//u_strlen((const UChar *)longName16);
				printf("Largo: %i\n",lenUTF16);
				
				int lenUTF8 = 0;
// 				unicode_utf16_to_utf8_inbuffer(longName16, lenUTF16, longName8, &lenUTF8);
				int i=0;
				for(i=0;i<26;i=i+2)
				{
				    if(longName16[i] == '\0' || longName16[i] == '.')
					break;
				    if(longName16[i] != '\0')
					longName8[i/2] = longName16[i];
				}   
// 				strcpy(longName8, "nadanada");
				printf("Nombre: %s\n",longName8);
				longName_flag =1;
				//free(longName16);
				//free(cadenaEnUTF8);
			}
// 			
	// 
	// 		size_t tamanioDeCadenaEnUTF16 = 26;
	// 		char *cadenaEnUTF8;
	// 		size_t tamanioDeCadenaEnUTF8 = 0;
	// 		//cadenaEnUTF8 = unicode_utf16_to_utf8((const uint16_t *)longName, tamanioDeCadenaEnUTF16, &tamanioDeCadenaEnUTF8);
	// 		
	// 		printf("LongName: %s - %s", cadenaEnUTF8, rtrim(cadenaEnUTF8,' '));
	// 		
	// 		longName_flag = 1;
	// 		
// 		    }
		    else
		    {
			for(z=j;z<(32+j);z++)
			{
				if((z-j) < 8)
				memcpy(&(dir->name)[z-j], &((data_sector)[z]), 1);
				if((z-j) >= 8 && (z-j) < 11)
				memcpy(&(dir->ext)[z-j-8], &((data_sector)[z]), 1);

				if((z-j) == 11)
				memcpy(&(dir->type), &((data_sector)[z]), 1);
				
				if((z-j) == 20)
				memcpy(&(aux_idCluster20), &((data_sector)[z]), 1);
				
				if((z-j) == 21)
				memcpy(&(aux_idCluster21), &((data_sector)[z]), 1);
				
				if((z-j) == 26)
				memcpy(&(aux_idCluster26), &((data_sector)[z]), 1);
				
				if((z-j) == 27)
				memcpy(&(aux_idCluster27), &((data_sector)[z]), 1); 
				
				if((z-j) == 28)
				memcpy(&(aux_idSize28), &((data_sector)[z]), 1);
				
				if((z-j) == 29)
				memcpy(&(aux_idSize29), &((data_sector)[z]), 1);
				
				if((z-j) == 30)
				memcpy(&(aux_idSize30), &((data_sector)[z]), 1);
				
				if((z-j) == 31)
				memcpy(&(aux_idSize31), &((data_sector)[z]), 1); 
				
			}
				strcpy(dir->longName,"null");
				if(longName_flag)
				{
					strcpy(dir->longName,longName8);
					longName_flag = 0;
				}
		    
			
			if(strncmp(dir->name,"TRASH",5))
			{
				if (dir->type == 32 || dir->type == 16)
				{
					//dir->idCluster = ((aux_idCluster20)[1]*100+(aux_idCluster20)[0])*100+((aux_idCluster26)[1]*100+(aux_idCluster26)[0]);
				
					aux_idCluster = aux_idCluster + aux_idCluster21;
					aux_idCluster =  aux_idCluster << 24;
					dir->idCluster = dir->idCluster | aux_idCluster;
					
					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster20;
					aux_idCluster =  aux_idCluster << 16;
					dir->idCluster = dir->idCluster | aux_idCluster;
					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster27;
					aux_idCluster =  aux_idCluster << 8;
					dir->idCluster = dir->idCluster | aux_idCluster;

					aux_idCluster =  0;
					aux_idCluster = aux_idCluster + aux_idCluster26;
					//aux_idCluster =  aux_idCluster << 24;
					dir->idCluster = dir->idCluster | aux_idCluster;
					
					if(dir->type == 32)
					{
					
					aux_size = aux_size + aux_idSize31;
					aux_size =  aux_size << 24;
					dir->size = dir->size | aux_size;
					
					aux_size =  0;
					aux_size = aux_size + aux_idSize30;
					aux_size =  aux_size << 16;
					dir->size = dir->size | aux_size;
					
					aux_size =  0;
					aux_size = aux_size + aux_idSize29;
					aux_size =  aux_size << 8;
					dir->size = dir->size | aux_size;

					aux_size =  0;
					aux_size = aux_size + aux_idSize28;
					dir->size = dir->size | aux_size;
					
					}
					else
					dir->size = 0;
				}
				else
					dir->idCluster = 0;
				
				
				if(dir->type > 0 && longName_flag == 0)
					addToList((gl *)dirs,dir);
			}
			}
		}
    }
//     free(longName16);
//     free(longName8);
    
    return 1;
}  


int addDirectoryInputsFromCluster(bootRegion* boot, cluster *dirCluster, directoryInputs* dirs)
{
 
    cluster *q = dirCluster; 
    cluster *aux;
    while (q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if(addDirectoryInputsFromSector(boot, (q->data->sec), dirs) == 0)
	{
// 	    while(q != NULL && q->data != NULL )
//  	    {
// 		aux = q;
// 		q = q->sgt;
// 		if(aux != NULL && aux->data != NULL && aux->data->sec != NULL)
// 		{
// 		    free(aux->data->sec);
// 		    free(aux->data);
// 		    free(aux);
// 		}
// 		else
// 		    return 0;
//  	    }
	    return 0;
	}
	
	q = q->sgt;
	
	
// 	while(q != NULL)
//  	{
// 	            aux = q;
// 		    q = q->sgt;
// 		    free(aux->data->sec);
// 		    free(aux->data);
// 		    free(aux);
//  	}

    }
    
    return 1;
}

int addDirectoryInputsFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directoryInputs* dirs)
{
    enum cluster_state state;
//     unsigned int mask = 0x0fffffff;
    sectors *listSectors;
    unsigned int aux_cluster_num, res = 1;

    do
    {
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt =NULL;
	
	cluster_num = cluster_num + boot->first_data_cluster  - 2;
// 	readCluster(disk, boot, cluster_num, 0, boot->cluster_size, listSectors);
	readClusterFromCache(disk, boot, "", cluster_num, 0, boot->cluster_size, listSectors);
	res = addDirectoryInputsFromCluster(boot, (cluster *)listSectors, dirs);
	
	cluster_num = cluster_num - boot->first_data_cluster  + 2;
	getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
	cluster_num = aux_cluster_num;
    
	
    } while((state == used)&&(res!=0));
        
    return 1;
}    

int addDirectoryContent(directory *direct,directoryInputs *dirs)
{
    if(dirs != NULL)
    {
	    directoryInputs *x = NULL;
	    directoryInputs *aux_x = NULL;
	    int l = 0;
	    x = dirs;

	    direct->content = (directory *) malloc (sizeof(directory));
	//     direct->content->data = (directoryInput *) malloc (sizeof(directoryInput));
	    direct->content->data = NULL;
	    direct->content->sgt = NULL;
	    //direct->sgt = NULL;
	    
	    while (x != NULL && x->data != NULL)
	    {
		if (x->data->type == 32 || x->data->type == 16)
		{
		    directoryInput *data = (directoryInput *) malloc (sizeof(directoryInput));
		    
		    //data->name = (char *) malloc (sizeof(char) * 9);
		    strcpy(data->name, x->data->name);
		    //data->ext = (char *) malloc (sizeof(char) * 4);
		    strcpy(data->ext, x->data->ext);
		    data->idCluster = x->data->idCluster;
		    data->type = x->data->type;
		    data->size = x->data->size;
	// 		data->longName = (char *) malloc (sizeof(char) * 14);
			if(x->data->longName != NULL)
			  strcpy(data->longName, x->data->longName);
			else
			  strcpy(data->longName, "null");
			
		    if (x->data->type == 16)
			pthread_mutex_init(&(data->dir_mutex), NULL);
		    
		    addToListWithSublist((glws *)direct->content, data, NULL);
		} 
		aux_x = x;
		x = x->sgt;
		free(aux_x->data);
		free(aux_x);
	    }   
    }
    return 1;
} 

int addDirectory(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directory* direct)
{
    directoryInputs *dirs = (directoryInputs *)malloc(sizeof(directoryInputs));
    dirs->data = NULL;
    dirs->sgt = NULL;
   
    unsigned int aux_cache_enabled = cache_enabled;
    cache_enabled = 0;
    addDirectoryInputsFromLinkedClusters(disk, boot, fatTable, cluster_num, dirs);
    cache_enabled = aux_cache_enabled;
    
    if(dirs != NULL && dirs->data != NULL)
	    addDirectoryContent(direct, dirs);
    else
	    direct->content = NULL;
    
    return 1;
}

int addDirectoryTree(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, directory* direct, int level)
{
    if (direct != NULL)
    {
	if (level > 0)
	{
	    
	    addDirectory(disk, boot, fatTable, direct->data->idCluster, direct);
	    
	    if ((level - 1) != 0)
	    {
		directory *p = direct->content;
		while (p != NULL)
		{
		    if(p->data->type == 16 && strcmp(p->data->name,".       ") && strcmp(p->data->name,"..      "))
			    addDirectoryTree(disk, boot, fatTable, p->data->idCluster, p, level - 1);
		    
		    p = p->sgt;
		}
	    }
		    
	}
	else 
	{
	    if (level == -1)
	    {
		addDirectory(disk, boot, fatTable, direct->data->idCluster, direct);
		
		directory *p = direct->content;
		while (p != NULL && p->data != NULL)
		{
		    if(p->data->type == 16 && strcmp(p->data->name,".       ") && strcmp(p->data->name,"..      "))
			    addDirectoryTree(disk, boot, fatTable, p->data->idCluster, p, level);
		    
		    p = p->sgt;
		}   
	    }
	}
	
	return 1;
    }
    else 
	return 0;
    
}

// int searchDirectory(directory *dir, char* name, directory *result)
// {
//     int lenght = 0;
//     directory *p = dir;
//     while (p != NULL)
//     {
// 	lenght = (int)strlen(name);
// 	if(p->data->type == 16 && (!strncmp(p->data->name,name,lenght)))
// 	    result=p;
// 	p = p->sgt;
//     } 
//     return 1;
// }

// int cutPath(const char *path,char *directory[])
// {
//     int i;
//     char *aux = (char *) malloc(sizeof(char) * strlen(path));
//     strcpy(aux,path);
//     directory[0] = strtok(aux,"/");
//     for(i = 1; (directory[i]= strtok(NULL, "/"));i++);
//     
//     free(aux);
//     return 1;
// }

int hotfat_open(const char *path, struct fuse_file_info *fi)
{
//     if(strcmp(path, "/CHELO") != 0)
//         return -ENOENT;
// 
//     if((fi->flags & 3) != O_RDONLY)
//         return -EACCES;

    if(createCacheFile(path, fi->flags))
	return 0;
    else
	return -1;
}

void hotfat_fullpath(char fpath[256], const char *path)
{
    
    strcpy(fpath, "/home/utn_so/prueba/chelo/");
    strncat(fpath, path, 512); // ridiculously long paths will
				    // break here

}


int hotfat_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
    size_t len;
    (void) fi;
    
    int flag = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0)
	{
        if(strcmp(path, "/") == 0)
	    {
// 	    	aux_size = 0;
	    }
	    else
	    {
		directory *q = (directory *) malloc(sizeof(directory));
		searchDirectory(path,root,&q);
		if(q->data->type == 32)
		{
		    if(offset > q->data->size)
			size = 0;
		    else
			if((size + offset) > q->data->size)
			    size = q->data->size - offset;
		    
		    if(size > 0)
		    {
			char *ret_str = (char *) malloc (sizeof(char) * size);
			unsigned int newSize = 0;
			
			readFileFromLinkedClusters(disk, boot, fatTablePointer, path, q->data->idCluster, offset, size, &ret_str, &newSize);
			
			size = newSize;
			memcpy(buf,ret_str,size);
			    
		    }
		    else
			strcpy(buf,"");
	    
		}
	    }
	}
    else
	strcpy(buf,"");
    
    return size;
    
}

// int readFileFromLinkedClusters(FILE* disk, bootRegion* boot, fatRegistry* fatTable, unsigned int cluster_num, char** content)
int readFileFromLinkedClusters(FILE* disk, bootRegion *boot, fatRegistry *fatTable, const char *path, unsigned int cluster_num, unsigned int offset, unsigned int size, char **content, unsigned int *newSize)
{    
    enum cluster_state state;
    sectors *listSectors = NULL;
    listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    sectors *aux_sector;
    unsigned int first_cluster_num = cluster_num;
    unsigned int aux_cluster_num;
    int aux_size = 0;
    *newSize = 0;
    
    unsigned int div_clusters_int, div_clusters_resto, div_total_size_resto;
    int div_total_size_int;
    unsigned int i = 0;
    
    div_clusters_int = offset / boot->cluster_size;
    div_clusters_resto = offset % boot->cluster_size;
    
    div_total_size_int = size / boot->cluster_size;
    div_total_size_resto = size % boot->cluster_size;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->cluster_size;
	div_total_size_int--;
    }
    
    state = used;
    
    while(state == used && i < div_clusters_int)
    {
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	if(state == used)
	    cluster_num = aux_cluster_num;
	
	i++;
	
    }
    
    if(i == div_clusters_int)
    {

	do
	{
	    
	    if(div_total_size_int == 0)
		aux_size = div_total_size_resto;
	    else
		aux_size = boot->cluster_size;
		
	    
// 	    readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, div_clusters_resto, aux_size, listSectors);
	    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, div_clusters_resto, aux_size, listSectors);														
	    
	    getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
	    
	    cluster_num = aux_cluster_num;
	    *newSize = *newSize + (aux_size - div_clusters_resto);
	    div_clusters_resto = 0;
	    div_total_size_int--;
	    i++;

	} while(state == used && div_total_size_int > 0);
	    
	
	aux_sector = listSectors;
	
	char *aux_text = (char *) malloc(sizeof(char) * (*newSize)); //+ 1));
	strcpy(aux_text,"");
	
	    
	div_total_size_int = (*newSize) / boot->bytes_per_sector;
	div_total_size_resto = (*newSize) % boot->bytes_per_sector;
	
	if(div_total_size_int > 0 && div_total_size_resto == 0)
	{
	    div_total_size_resto = boot->bytes_per_sector;
	    div_total_size_int--;
	}
    
	unsigned int copied = 0;
   
   *newSize = 0;
	while(aux_sector!= NULL && aux_sector->data != NULL && aux_sector->data->sec != NULL && copied < div_total_size_int)
	{
	    memcpy((aux_text+(copied*boot->bytes_per_sector)), aux_sector->data->sec, boot->bytes_per_sector);
	    
	    *newSize = *newSize + boot->bytes_per_sector;
// 	    sectors *free_sec;
// 	    free_sec = aux_sector;
	    aux_sector = aux_sector->sgt;
// 	    free(free_sec->data->sec);
// 	    free(free_sec->data);
	    copied++;
	}
	if(aux_sector!= NULL && aux_sector->data != NULL && aux_sector->data->sec != NULL && copied == div_total_size_int)
	{
	    memcpy((aux_text+(copied*boot->bytes_per_sector)), aux_sector->data->sec, div_total_size_resto);
	    
	    *newSize = *newSize + div_total_size_resto;
       
       
// 	    sectors *free_sec;
// 	    free_sec = aux_sector;
	    aux_sector = aux_sector->sgt;
// 	    free(free_sec->data->sec);
// 	    free(free_sec->data);
	}
	
// 	while(listSectors!= NULL)
// 	{
// 	    aux_sector = listSectors;
// 	    listSectors = listSectors->sgt;
// 	}

	memcpy(*content, aux_text, *newSize);

    }
    else 
    {
	strcpy(*content, (char *) "");
	return 0;
    }
    
    
    return 1;
    
}


int writeSector(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector)
{

    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    char *data_send = (char *) malloc(sizeof(char) * size);
    
    rInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
    enviarIPC(iSocketConectado,&rInfoIPC);
    free(rInfoIPC.payload);
    
    recibirIPC(iSocketConectado,&rInfoIPC);
    free(rInfoIPC.payload);
    if(rInfoIPC.payLoadDescriptor == HSOK)
    {
	sprintf(num_sector_str, "%u", num_sector);
	rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
	{
	    rInfoIPC.payLoadLength = 512;
	    memcpy(data_send, data_sector + offset, size);
	    generarStructIPC(data_send,SET_SECTORES,&rInfoIPC);
	    enviarIPC(iSocketConectado,&rInfoIPC);
	    free(rInfoIPC.payload);
	    
	    recibirIPC(iSocketConectado,&rInfoIPC);
	    free(rInfoIPC.payload);
	    if(rInfoIPC.payLoadDescriptor != RTA_SET_SECTORES)
	    {
		close(iSocketConectado);
		free(num_sector_str);
		free(data_send);
		return -1;
	    }
	    
	}
	else
	    {
		close(iSocketConectado);
		free(num_sector_str);
		free(data_send);
		return -1;
	    }
	
    }
    
    close(iSocketConectado);
    free(num_sector_str);
    free(data_send);
    
    return 1;
    
//     if (disk == NULL)
//     {
// 	printf("Error al leer el archivo\n");
// 	return 0;
//     }
//     else
//     {
// 	fseek(disk,(num_sector * boot->bytes_per_sector) + offset ,SEEK_SET);
// 	fwrite(data_sector, 1, (size - offset), disk);
//     }  
//     
//     return 1;
}


int writeCluster(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
//     for(;i< boot->sectors_per_cluster && q != NULL;i++)
	
    while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	writeSector(disk, boot, (num_cluster * boot->sectors_per_cluster) + i, div_sectors_resto, aux_size, q->data->sec);
	
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    
//     while(listSectors != NULL && counter <= boot->sectors_per_cluster)
//     {
// 	i = (num_cluster * boot->sectors_per_cluster) + counter;
// 	
// 	writeSector(disk, boot, i, listSectors->data->sec);
// 	
// 	aux_sec = listSectors;
// 	listSectors = listSectors->sgt;
// 	free(aux_sec);
// 	
// 	counter = counter + 1;
//     }
// 	
//     if(q != NULL)
// 	return 0; //Error
//     else
	return 1; //Todo OK!
}



// int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
// {
// 
//     
//     sectors *aux_sec;
//     int i;
//     unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
//         
//     div_sectors_int = offset / boot->bytes_per_sector;
//     div_sectors_resto = offset % boot->bytes_per_sector;
//     
//     div_total_size_int = size / boot->bytes_per_sector;
//     div_total_size_resto = size % boot->bytes_per_sector;
//     
//     if(div_total_size_int > 0 && div_total_size_resto == 0)
//     {
// 	div_total_size_resto = boot->bytes_per_sector;
// 	div_total_size_int--;
//     }
//     
//     sectors *q = listSectors;
//     
//     for(i=0;i< div_sectors_int && q != NULL;i++)
// 	q = q->sgt;
//     
//     
//     int iSocketConectado = crearSocket(AF_INET);
//     Conectar2(iSocketConectado, ipDisco, puertoDisco);	
//     
//     InfoIPC hsInfoIPC;
//     
//     hsInfoIPC.payLoadLength = 5;
//     generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
//     enviarIPC(iSocketConectado,&hsInfoIPC);
//     
//     recibirIPC(iSocketConectado,&hsInfoIPC);
//     if(hsInfoIPC.payLoadDescriptor == HSOK)
//     {
// 	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
// 	int cant = 0;
// 	while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL)
// 	{
// 	    if(i == div_total_size_int)
// 		aux_size = div_total_size_resto;
// 	    else
// 		aux_size = boot->bytes_per_sector;
// 	    
// 	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
// 	    cluster_data[cant].offset = div_sectors_resto;
// 	    cluster_data[cant].size = aux_size;
// 	    cluster_data[cant].wrote = 0;
// 	    
// 	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
// 	    InfoIPC sInfoIPC;
// 	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
// 	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
// 	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
// 	    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&sInfoIPC);
// 	    enviarIPC(iSocketConectado ,&sInfoIPC);
// 	    
// // 	    recibirIPC(iSocketConectado,&sInfoIPC);
// // 	    if(sInfoIPC.payLoadDescriptor == WRITE_SECTOR_REQUEST)
// // 	    {
// 		sInfoIPC.payLoadLength = aux_size;
// 		char *data_send = (char *) malloc(sizeof(char) * aux_size);
// 		memcpy(data_send, q->data->sec + div_sectors_resto, aux_size);
// 		generarStructIPC(data_send,SET_SECTORES_LAST,&sInfoIPC);
// 		enviarIPC(iSocketConectado,&sInfoIPC);
// 		
// 		cant++;
// 		free(data_send);
// 		
// // 	    }
// // 	    else
// // 	    {
// // 		close(iSocketConectado);
// // 		free(cluster_data);
// // 		return -1;
// // 	    }
// 	    
// 	    free(num_sector_str);
// 	    
// 	    div_sectors_resto = 0;
// 	    q = q->sgt;
// 	    i++;
// 	}
// 	
// 	unsigned int max_sock = 0;
// 	fd_set set_socket;
// 	FD_SET(iSocketConectado, &set_socket);
// 	
// 	struct timeval timeout;
// 	int rv;
// 	
// 	timeout.tv_sec = 3;
// 	timeout.tv_usec = 0;
// 
// 	int j=0;
// 	int w=0;
// 	int done = 0;
// 	i=0;
// 	
// 	while(w < cant)
// 	{
// 	    FD_ZERO(&set_socket);
// 	    FD_SET(iSocketConectado, &set_socket);
// 	    
// 	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, &timeout);
// 	    if(rv == -1){
// 		printf("Llamada del Select error\n");
// 		FD_CLR(iSocketConectado, &set_socket);
// 		close(iSocketConectado);
// 		free(cluster_data);
// 		return -1;
// 	    }
// 	    if(rv == 0)
// 		break;
// 	    
// 	    if(FD_ISSET(iSocketConectado, &set_socket))
// 	    {
// 		InfoIPC rInfoIPC;
// 		unsigned int nro_pedido, nro_sector;
// 		recibirIPC(iSocketConectado,&rInfoIPC);
// 		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
// 		{
// 		    nro_pedido = atoi(rInfoIPC.payload);
// 		
// 		    recibirIPC(iSocketConectado,&rInfoIPC);
// 		    if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
// 		    {
// 			nro_sector = atoi(rInfoIPC.payload);
// 			for(j=0;j<cant;j++)
// 			    if(cluster_data[j].sector_num == nro_sector)
// 				cluster_data[j].wrote = 1;
// 			    
// 			w++;
// 		    }
// 		    else
// 			cluster_data[j].wrote = 4;
// 		}
// 		else
// 		{
// 		    rv = 0;
// 		    break;
// 		}
// 	    }
// 	    
// 	    FD_CLR(iSocketConectado, &set_socket);
// 	    
// 	}
// 	
// 	close(iSocketConectado);
// 	
// 	int retv = 0;
// 	if(w < cant && rv == 0)
// 	    retv = writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
// 	else
// 	{
// 	    for(i=0;i<cant;i++)
// 	    {
// 		if(cluster_data[j].wrote == 4)
// 		{
// 		    free(cluster_data);
// 		    return -1;
// 		}
// 	    }
// 	    retv = 1;
// 	}
// 	free(cluster_data);
// 	
// 	return retv;
//     }
//     else
//     {
// 	close(iSocketConectado);
// 	return -1;
//     }
// 
// }


int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    char sContador[20];
//     int iSocketConectado;
    InfoIPC rInfoIPC;
    int contador=i;
    fd_set set_socketsHiloPrincipal;
    cliente *pNodoCliente,*pAuxCliente;
    int iMayorSocket;
    cliente* ListaClientes=NULL;
    cliente* ListaClientes_Ult=NULL;

    int numero = num_cluster * boot->sectors_per_cluster + i;
    
    /*Creo 8 socketes y envio escrituras de 8 numeros*/
    
    while(contador < boot->sectors_per_cluster)
    {
	
	q = listSectors;
	
	/*HANDSHAKE*/ 
	int iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado,ipDisco,puertoDisco);	
	rInfoIPC.payLoadLength=5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	recibirIPC(iSocketConectado,&rInfoIPC);
	free(rInfoIPC.payload);
	
	if(rInfoIPC.payLoadDescriptor== HSOK){
	
	    pNodoCliente = (cliente *)malloc(sizeof(cliente));
	    pNodoCliente->socketCliente=iSocketConectado;
	    agregarAListaDeClientes(&pNodoCliente,&ListaClientes,&ListaClientes_Ult);
	    
	    intacad((contador+numero),sContador);
	    rInfoIPC.payLoadLength=strlen(sContador)+1;
	    generarStructIPC(sContador,WRITE_SECTOR_REQUEST,&rInfoIPC);
	    enviarIPC(iSocketConectado,&rInfoIPC);
	    free(rInfoIPC.payload);
    
	    rInfoIPC.payLoadLength=512;
	    generarStructIPC(q->data->sec, SET_SECTORES_LAST ,&rInfoIPC);
	    enviarIPC(iSocketConectado,&rInfoIPC);
	    free(rInfoIPC.payload);
	    
	}
	
	listSectors = listSectors->sgt;
	free(q->data->sec);
	free(q->data);
	q->sgt = NULL;
	q->data = NULL;
	free(q);
	
	contador++;
    }
    
    /*Escucho respuestas en esos sockets*/
    
    while(ListaClientes!=NULL)
    {
	
	FD_ZERO(&set_socketsHiloPrincipal);
	pAuxCliente = ListaClientes;
	while(pAuxCliente != NULL)
	{
	    FD_SET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal);	
	    if(pAuxCliente->socketCliente > iMayorSocket)
		iMayorSocket = pAuxCliente->socketCliente;
	    pAuxCliente = pAuxCliente->Sgt;
	}
	
	
	select(iMayorSocket + 1,&set_socketsHiloPrincipal, NULL, NULL,NULL);
	
	pAuxCliente = ListaClientes;
	while(pAuxCliente != NULL)
	{
	    if( FD_ISSET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal ) > 0 ){
		break;
	    }
	    pAuxCliente = pAuxCliente->Sgt;
	}
	if(pAuxCliente != NULL)
	{		
	    recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
// 	    printf("Recibi confirmacion de escritura de sector: %s \n",(char *)rInfoIPC.payload);
	    free(rInfoIPC.payload);
	    /*Se desconecta cliente*/
	    close(pAuxCliente->socketCliente);
	    FD_CLR(pAuxCliente->socketCliente, &set_socketsHiloPrincipal);
	    SacarDeLista_Clientes(&pAuxCliente,&ListaClientes,&ListaClientes_Ult);
	    free(pAuxCliente);
		
	}

    }
    
    
    return 1;
}
/*
int writeClusterNIPC(FILE* disk, bootRegion* boot, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{

    
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    
    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC hsInfoIPC;
    
    hsInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&hsInfoIPC);
    enviarIPC(iSocketConectado,&hsInfoIPC);
    
    recibirIPC(iSocketConectado,&hsInfoIPC);
    if(hsInfoIPC.payLoadDescriptor == HSOK)
    {
	nipcCluster *cluster_data = (nipcCluster *) malloc ((boot->sectors_per_cluster - i) * sizeof(nipcCluster));
	int cant = 0;
	while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL && q->data != NULL && q->data->sec != NULL)
	{
	    if(i == div_total_size_int)
		aux_size = div_total_size_resto;
	    else
		aux_size = boot->bytes_per_sector;
	    
	    cluster_data[cant].sector_num = i + (num_cluster * boot->sectors_per_cluster);
	    cluster_data[cant].offset = div_sectors_resto;
	    cluster_data[cant].size = aux_size;
	    cluster_data[cant].wrote = 0;
	    
	    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
	    InfoIPC sInfoIPC;
	    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
	    sprintf(num_sector_str, "%u", cluster_data[cant].sector_num);
	    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
	    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&sInfoIPC);
	    enviarIPC(iSocketConectado ,&sInfoIPC);
	    
	    recibirIPC(iSocketConectado,&sInfoIPC);
	    if(sInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
	    {
		sInfoIPC.payLoadLength = aux_size;
		char *data_send = (char *) malloc(sizeof(char) * aux_size);
		memcpy(data_send, q->data->sec + div_sectors_resto, aux_size);
		generarStructIPC(data_send,SET_SECTORES,&sInfoIPC);
		enviarIPC(iSocketConectado,&sInfoIPC);
		
		cant++;
		free(data_send);
		
	    }
	    else
	    {
		close(iSocketConectado);
		free(cluster_data);
		return -1;
	    }
	    
	    free(num_sector_str);
	    
	    div_sectors_resto = 0;
	    q = q->sgt;
	    i++;
	}
	
	unsigned int max_sock = 0;
	fd_set set_socket;
	FD_SET(iSocketConectado, &set_socket);
	
	struct timeval timeout;
	int rv;
	
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;

	int j=0;
	int w=0;
	int done = 0;
	i=0;
	
	while(w < cant)
	{
	    FD_ZERO(&set_socket);
	    FD_SET(iSocketConectado, &set_socket);
	    
	    rv = select(iSocketConectado+1, &set_socket, NULL, NULL, &timeout);
	    if(rv == -1){
		printf("Llamada del Select error\n");
		FD_CLR(iSocketConectado, &set_socket);
		close(iSocketConectado);
		free(cluster_data);
		return -1;
	    }
	    if(rv == 0)
		break;
	    
	    if(FD_ISSET(iSocketConectado, &set_socket))
	    {
		InfoIPC rInfoIPC;
		unsigned int nro_pedido, nro_sector;
// 		recibirIPC(iSocketConectado,&rInfoIPC);
// 		if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
// 		{
// 		    nro_pedido = atoi(rInfoIPC.payload);
		
		    recibirIPC(iSocketConectado,&rInfoIPC);
		    if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
		    {
			nro_sector = atoi(rInfoIPC.payload);
			for(j=0;j<cant;j++)
			    if(cluster_data[j].sector_num == nro_sector)
				cluster_data[j].wrote = 1;
			    
			w++;
		    }
		    else
			cluster_data[j].wrote = 4;
// 		}
// 		else
// 		{
// 		    rv = 0;
// 		    break;
// 		}
	    }
	    
	    FD_CLR(iSocketConectado, &set_socket);
	    
	}
	
	close(iSocketConectado);
	
	int retv = 0;
	if(w < cant && rv == 0)
	    retv = writeClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
	else
	{
	    for(i=0;i<cant;i++)
	    {
		if(cluster_data[j].wrote == 4)
		{
		    free(cluster_data);
		    return -1;
		}
	    }
	    retv = 1;
	}
	free(cluster_data);
	
	return retv;
    }
    else
    {
	close(iSocketConectado);
	return -1;
    }

}*/



// int getFileSize(FILE* disk, bootRegion* boot, fatRegistry* fatTable, const char *path, unsigned int cluster_num, int* size)
// {    
//     enum cluster_state state;
// //     unsigned int mask = 0x0fffffff;
//     sectors *listSectors = NULL;
//     listSectors = (sectors *) malloc(sizeof(sectors));
//     listSectors->data = NULL;
//     unsigned int aux_cluster_num;
//     int size2 = 0;
//     
//     if(cluster_num > 0)
//     {
// 	
// 	do
// 	{	
// 	    
// 	    getClusterState(fatTable, cluster_num, &state, &aux_cluster_num);
// 	    
// 	    if(state == used)
// 		size2 = size2 + boot->cluster_size;
// 		
// 	    if(state == last)
// 	    {
// // 		readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
// 		readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
// 		
// // 		sectors *aux_sector;
// 		
// 		while(listSectors != NULL)
// 		{
// 		    if(listSectors->data != NULL)
// 		    {
// 			if(listSectors->data->sec != NULL)
// 			{
// 			    size2 = size2 + strlen(listSectors->data->sec);
// 			}
// 		    }
// 		    
// 		    listSectors = listSectors->sgt;
// 		}
// 		    
// 	    }
// 	    
// 	    cluster_num = aux_cluster_num;
// 	    
// 	} while(state == used);
//     
//     }
//     else
// 	size2 = 0;
// 	
//     *size = size2;
//     
//     return 1;
//     
// }


int hotfat_truncate(const char *path, off_t offset)
{
 
    int flag = 0, aux_size = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0){
        if(strcmp(path, "/") == 0) {
	    
	}
	else
	{
	    directory *q = (directory *) malloc(sizeof(directory*));
		searchDirectory(path,root,&q);
		    if(q->data->type == 32)
		    {
			
			int div_clusters_int;
			int div_clusters_resto;
			int i = 0, first_time;
			unsigned int aux_cluster_num, cluster_num;
			enum cluster_state state;
			unsigned int free_cluster_num;
			
			cluster_num = q->data->idCluster;
			aux_cluster_num = q->data->idCluster;
			
			aux_size = q->data->size;
			
			if(q->data->idCluster == 0)
			{
			    getFreeCluster(freeClusters, &free_cluster_num);
			    q->data->idCluster = free_cluster_num;
			    setUsedCluster(freeClusters, 0x0FFFFFF8, q->data->idCluster);
			}
		    
		    
			if(offset < aux_size)
			{
			    sectors *listSectors = NULL;
			    listSectors = (sectors *) malloc(sizeof(sectors));
			    listSectors->data = NULL;
			    listSectors->sgt = NULL;
			    
			    i = 0;
			    div_clusters_int = offset / boot->cluster_size;
			    div_clusters_resto = offset % boot->cluster_size;
			    
			    state = used;
			    
			    while(state == used && i < div_clusters_int)
			    {
				getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				
				if(state == used)
				    cluster_num = aux_cluster_num;
				
				i++;
				
			    }
			
			    if(i == div_clusters_int)
			    {    
				if(div_clusters_resto > 0)
				{
// 					readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    truncateCluster(&listSectors, div_clusters_resto);
// 					writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				}
				
				first_time = 1;
				
				do
				{
				    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				    
				    if(state == used || state == last)
				    {
					if(first_time == 1)
					{
					    fatTablePointer[cluster_num] = 0x0FFFFFF8;
					    first_time = 0;
					}
					else
					    setFreeCluster(freeClusters, cluster_num);
				    }
				    
				    cluster_num = aux_cluster_num;
				    
				} while(state == used);
			    }
			}
			else if(offset > aux_size)
			{
			    
			    i = 0;
			    div_clusters_int = offset / boot->cluster_size;
			    div_clusters_resto = offset % boot->cluster_size;
			    
			    
			    do
			    {
				i++;
				getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
				
				if(state == used)
				    cluster_num = aux_cluster_num;
				
			    } while(state == used && i <= div_clusters_int);
			    
			    
			    if(state == last)
			    {
				i--;
				
				int aux_offset = aux_size - (i * boot->cluster_size);
				int final_byte = boot->cluster_size;
				unsigned int content, free_cluster_num = 0;
				sectors *listSectors = NULL;
				listSectors = (sectors *) malloc(sizeof(sectors));
				listSectors->data = NULL;
				listSectors->sgt = NULL;
				
				
				do
				{
				    if(i == div_clusters_int)
				    {
					final_byte = div_clusters_resto;
					content = 0x0FFFFFF8;
				    }
				    else
				    {
					getFreeCluster(freeClusters, &free_cluster_num);
					content = 0x00000000 + free_cluster_num;
				    }
				    
// 					readCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    readClusterFromCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    increaseCluster(listSectors, aux_offset, final_byte);
// 					writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
				    
				    setUsedCluster(freeClusters, content, cluster_num);
				    
				    listSectors = (sectors *) malloc(sizeof(sectors));
				    listSectors->data = NULL;
				    listSectors->sgt = NULL;
				
				    aux_offset = 0;
				    cluster_num = free_cluster_num;
				    i++;
				    
				} while(i <= div_clusters_int);
				
			    }
			    else
				return -1;
			    
			    
			}
			q->data->size = offset;
			
			    
			if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
			    printf("pthread_mutex_lock\n");
			    exit(EXIT_FAILURE);
			}
			cacheFiles *w = fileDescriptorsTable;
			while(w != NULL && w->data != NULL && strcmp(w->data->path, path))
			    w = w->sgt;
			
			if(w != NULL && w->data != NULL)
			    if(w->data->cant_opens > 0)
			    {
				w->data->change_size = 0;//w->data->wrote + offset;
				w->data->release_size = 1;
			    }
			    
			if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
			    printf("pthread_mutex_lock\n");
			    exit(EXIT_FAILURE);
			}
			    
		    }
		}
		
    
// 	    saveFAT(disk, boot, fatTablePointer);
	    
	
    }
    
    
    return 0;
}

int truncateCluster(sectors **listSectors, int offset)
{
    int i, div_sectors_int, div_sectors_resto;
    sectors *q = *listSectors;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    for(;i<boot->sectors_per_cluster && q != NULL;i++)
    {
	truncateSector(&(q->data->sec), div_sectors_resto);
	div_sectors_resto = 0;
	q = q->sgt;
    }
    
    return 1;
}

int truncateSector(char **data_sector, int offset)
{
    memset((*data_sector)+offset, 0,(boot->bytes_per_sector - offset));
    return 1;
}


int increaseCluster(sectors *listSectors, int offset, int final_byte)
{
    int i, div_sectors_int, div_sectors_resto;
    sectors *q = listSectors;
    
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
	q = q->sgt;
    
    while(i<boot->sectors_per_cluster && q != NULL)
    {
	if((final_byte - (i * boot->bytes_per_sector)) < boot->bytes_per_sector)
	{
	    increaseSector(&(q->data->sec), div_sectors_resto, final_byte - (i * boot->bytes_per_sector));
	    if(final_byte < boot->cluster_size)
		truncateCluster(&listSectors, final_byte);
	    return 1;
	}
	else
	    increaseSector(&(q->data->sec), div_sectors_resto, boot->bytes_per_sector);
	
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    return 1;
}

int increaseSector(char **data_sector, int offset, int final_byte)
{
    memset((*data_sector)+offset, '\0',(final_byte - offset));
    return 1;
}


int getClusterState(fatRegistry *fatTable, unsigned int cluster_num, enum cluster_state *state, unsigned int *cluster_registry)
{
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    unsigned int mask = 0x0fffffff;
    *cluster_registry = (int) (fatTable[cluster_num] & mask);

    switch(*cluster_registry)
    {
	case 0x00000000:
	    *state = free_cluster;
	break;
	case 0x00000001:
	    *state = reserved;
	break;
	case 0x0FFFFFF6:
	    *state = reserved;
	break;
	case 0x0FFFFFF7:
	    *state = bad;
	break;
	default:
	    if(*cluster_registry >= 0x00000002 && *cluster_registry <= 0x0FFFFFEF)
	    {
		*state = used;
	    } 
	    else if (*cluster_registry >= 0x0FFFFFF8 || *cluster_registry <= 0x0FFFFFFF)
	    {
		*state = last;
	    } 
	    else
		*state = error;
	break;
    }
    
    return 1;
}

int saveFAT(FILE* disk, bootRegion *boot, fatRegistry *fatTable)
{
    unsigned int last_loaded, num_sector;
    int i;
    
    num_sector = boot->count_sect_reservados;
    
    int iSocketConectado = crearSocket(AF_INET);
    Conectar2(iSocketConectado, ipDisco, puertoDisco);	
    
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    rInfoIPC.payLoadLength = 5;
    generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
    
    enviarIPC(iSocketConectado,&rInfoIPC);
    free(rInfoIPC.payload);
    
    recibirIPC(iSocketConectado,&rInfoIPC);
    free(rInfoIPC.payload);
    if(rInfoIPC.payLoadDescriptor == HSOK)
    {
	last_loaded = 0;
	for (i = 0;i< boot->fat32_size;i++)
	{
	    writeSectorFromFAT(disk, boot, num_sector + i, fatTable, last_loaded, iSocketConectado);
	    last_loaded += (boot->bytes_per_sector/4);
	}
    }
    
    int m;
    for(m=0;m<boot->count_clusters_fat;m++)
	modifyPointer[m]=0;
    
    close(iSocketConectado);
	
    
    return 1;
}

int writeSectorFromFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, fatRegistry *fatTable, unsigned int last_loaded, int iSocketConectado)
{
    
    int i, j, modified = 0;
    
    for(i=0,j=last_loaded;i< boot->bytes_per_sector && modified == 0;i+=4,j++)
	if(modifyPointer[j] == 1)
	    modified = 1;
    
    if(modified == 1)
    {
	char *data_sector = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
	for(i=0,j=last_loaded;i< boot->bytes_per_sector;i+=4,j++)
	    memcpy(&data_sector[i],&fatTable[j],4);
	
	//Imprimo las dos FATTable
	writeSectorFAT(disk, boot, num_sector, 0, boot->bytes_per_sector, data_sector, iSocketConectado);
	writeSectorFAT(disk, boot, num_sector+ boot->fat32_size, 0, boot->bytes_per_sector, data_sector, iSocketConectado);

	free(data_sector);
    }
    
    return 1;
}

int setFreeCluster(char* freeClusters, unsigned int cluster_num)
{
    
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    clusterIds *aux_list = (clusterIds *) malloc (sizeof(clusterIds));
    aux_list->data = (clusterId *) malloc (sizeof(clusterId));
    
    fatTablePointer[cluster_num] = 0x00000000;
    modifyPointer[cluster_num] = 1;
    
    *(aux_list->data) = cluster_num;
    aux_list->sgt = NULL;
    addFreeClusters(freeClusters, aux_list);
    
    free(aux_list->data);
    free(aux_list);
    
    return 1;
}

int getFreeCluster(char* freeClusters, unsigned int *cluster_num)
{
    
    int i = 0;
    
    if(freeClusters != NULL)
    {
	
	while(i < boot->count_clusters_fat)
	{
	    if(i < clusters_loaded_FAT)
	    {
		if(freeClusters[i] == '0')
		{
		    *cluster_num = i;
		    return 1;
		}
		    
		i++;
	    }
	    else
	    {
		loadFAT(disk, boot, fatTablePointer);
		loadFreeClusters(boot, fatTablePointer, freeClusters);
	    }
	}
    }
    
    
    *cluster_num = -1;
    return 0;
}

int setUsedCluster(char *freeClusters, unsigned int content, unsigned int cluster_num)
{
    while(clusters_loaded_FAT < cluster_num)
	loadFAT(disk, boot, fatTablePointer);
    
    clusterIds *aux_list = (clusterIds *) malloc (sizeof(clusterIds));
    aux_list->data = (clusterId *) malloc (sizeof(clusterId));
    
    fatTablePointer[cluster_num] = content;
    modifyPointer[cluster_num] = 1;
    
    *(aux_list->data) = cluster_num;
    aux_list->sgt = NULL;
    deleteFreeClusters(freeClusters, aux_list);
    
    free(aux_list->data);
    free(aux_list);
    
    return 1;
}


int fillWithChar(char **string, char fill_char, int total_size)
{
    int i = 0;
    
    while((i< total_size) && ((*string)[i] != '\0'))
	i++;
    
    for( ;i < total_size; i++)
	(*string)[i] = fill_char;
    
    return 1;
}

int hotfat_create(const char *path, mode_t mode, struct fuse_file_info *fi)
{
    //Buscar dir padre
    char *pathFather = (char *) malloc(sizeof(char)*256);
	fatherName(path,pathFather);
	
	
    directory *q;// = (directory *) malloc(sizeof(directory));
    searchDirectory(pathFather,root,&q);
    
    directoryInput *new_input = (directoryInput *) malloc (sizeof(directoryInput));
    char *name = (char *) malloc (sizeof(char) * 18);
    if(strchr(path,'.') != NULL)
    {
		char *aux_path = (char *) malloc (sizeof(char) * strlen(path));
		newName(path, aux_path);
		strcpy(name, strtok(aux_path,"."));
		strcpy(new_input->ext, strtok(NULL,"\n\0"));
    }
    else
    {
		//char *name = (char *) malloc (sizeof(char) * 9);
		newName(path,name);
		strcpy(new_input->ext, "   ");
    }
    
	
	if(strlen(name)<=8)
	{
		strcpy(new_input->name,name);
		strcpy(new_input->longName,"null");
	}
	else
	{
		memset(new_input->name, '\0', 9);
		memcpy(new_input->name,name,8);
		memset(new_input->longName,'\0',14);
		memcpy(new_input->longName,name,13);
	}
    
    
    
    new_input->idCluster = 0;
    new_input->size = 0;
    new_input->type = 32;
    
    if(strcmp(new_input->longName,"null"))
    {
	char *aux_longDirect = (char *) malloc(sizeof(char) * (32+1));
	createLongNameInput(&aux_longDirect,new_input);
	pthread_mutex_lock(&(q->data->dir_mutex));
	saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_longDirect, 1);
	pthread_mutex_unlock(&(q->data->dir_mutex));
	free(aux_longDirect);
    }
    
    char *aux_direct = (char *) malloc(sizeof(char) * (32+1));
    createDirectoryInput(&aux_direct, new_input);
    pthread_mutex_lock(&(q->data->dir_mutex));
    if(saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_direct, 1))
    {
	pthread_mutex_unlock(&(q->data->dir_mutex));
	if(q->content == NULL)
	{
		q->content = (directory *) malloc(sizeof(directory));
		q->content->data = NULL;
		q->content->content = NULL;
		q->content->sgt = NULL;
	}
	addToListWithSublist((glws *)q->content, new_input, NULL);
	
	hotfat_open(path,fi);
	free(aux_direct);
	return 0;
    }
    else
    {
	pthread_mutex_unlock(&(q->data->dir_mutex));
	free(aux_direct);
	return -1;
    }
    
    return -1;
}

// int hotfat_mknod(const char *path, mode_t mode , dev_t dev)
// {
//     
//     return 0;
// }

int createDirectoryInput(char **data_dir32, directoryInput *dir)
{
//   uint8_t name[8];
//   uint8_t ext[3];
//   uint8_t type;
//   uint64_t ocho_ceros;
//   uint16_t high_first_cluster;
//   uint32_t cuatro_ceros;
//   uint16_t low_first_cluster;
//   uint32_t size;
    
    
    directoryInputRegistry *aux_data_dir32 = (directoryInputRegistry *) malloc (sizeof(directoryInputRegistry));
    memset(aux_data_dir32, 0, sizeof(directoryInputRegistry));
    
    char *aux_name = (char *) malloc(sizeof(char) * 9);
    char *aux_ext = (char *) malloc(sizeof(char) * 4);
    
    strcpy(aux_name, dir->name);
    fillWithChar(&aux_name, ' ', 8);
    memcpy(aux_data_dir32->name, aux_name, 8);
    
    strcpy(aux_ext, dir->ext);
    fillWithChar(&aux_ext, ' ', 3);
    memcpy(aux_data_dir32->ext, aux_ext, 3);
    
    aux_data_dir32->type = (uint8_t) dir->type;
    aux_data_dir32->low_first_cluster = dir->idCluster & 0x0000FFFF;
    aux_data_dir32->high_first_cluster = dir->idCluster >> 8;
    
    uint32_t aux_size = 0;
    uint8_t aux_idSize[4];
    
    memcpy(&aux_idSize, &(dir->size), sizeof(uint32_t));
    
    aux_size = aux_size + aux_idSize[0];
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    aux_size =  0;
    aux_size = aux_size + aux_idSize[1];
    aux_size =  aux_size << 8;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    aux_size =  0;
    aux_size = aux_size + aux_idSize[2];
    aux_size =  aux_size << 16;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;

    aux_size =  0;
    aux_size = aux_size + aux_idSize[3];
    aux_size =  aux_size << 24;
    aux_data_dir32->size = aux_data_dir32->size | aux_size;
    
    
    memcpy((*data_dir32), aux_data_dir32, sizeof(directoryInputRegistry));
//     sprintf(*data_dir32,"%s\n",*data_dir32);
    
    return 1;
}


int createLongNameInput(char **data_dir32, directoryInput *dir)
{
	char *entryDir = (char *) malloc(sizeof(char)*14);
	char *auxUTF8 = (char *) malloc(sizeof(char)*14);
	char *auxUTF16 = (char *) malloc(sizeof(char)*28);
	int len16;
	strcpy(entryDir,dir->longName);	
	int lenName = strlen(entryDir);
	memset((*data_dir32),'\0',32);	
	
	*(*data_dir32) = 'A';
	
	if(lenName>0)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);
		strncpy(auxUTF8,entryDir,5);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),(uint16_t *)auxUTF16,&len16);
		memcpy((*data_dir32)+1,auxUTF16,len16*2);
	}
	
	*((*data_dir32)+11) = 0xF;	
	*((*data_dir32)+12) = 0x0;
	*((*data_dir32)+13) = 0x0;

	if(lenName>5)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);		
		strncpy(auxUTF8,entryDir+5,6);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),(uint16_t *)auxUTF16,&len16);
		memcpy((*data_dir32)+14,auxUTF16,len16*2);
	}

	*((*data_dir32)+26) = 0x0;
	*((*data_dir32)+27) = 000;

	if(lenName>11)
	{
		memset(auxUTF8,'\0',14);
		memset(auxUTF16,'\0',28);		
		strncpy(auxUTF8,entryDir+11,2);
		len16 = 0;
		unicode_utf8_to_utf16_inbuffer(auxUTF8,strlen(auxUTF8),(uint16_t *)auxUTF16,&len16);
		memcpy((*data_dir32)+28,auxUTF16,len16*2);
	}
	
    return 1;
}

int writeFileFromLinkedClusters(FILE *disk, bootRegion *boot, const char *path, fatRegistry *fatTable, unsigned int cluster_num, unsigned int old_size, unsigned int offset, unsigned int size, const char *content, unsigned int *wrote)
{    
    
    unsigned int total_clusters_int, total_clusters_mod, aux_offset_int, aux_offset_mod, aux_size;
    enum cluster_state state;
    unsigned int aux_cluster_num, free_cluster_num, registry;
    
    sectors *listSectors = NULL;
    listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    
    *wrote = 0;
    
    aux_offset_int = offset / boot->cluster_size;
    aux_offset_mod = offset % boot->cluster_size;
    total_clusters_int = (size + offset) / boot->cluster_size;
    total_clusters_mod = (size + offset) % boot->cluster_size;
    
    if(total_clusters_int > 0 && total_clusters_mod == 0)
    {
	total_clusters_mod = boot->cluster_size;
	total_clusters_int--;
    }
    
    int i = 0;
    if(aux_offset_int == 0)
	state = last;
    else
	state = used;
    
    while(state == used && i < aux_offset_int)
    {
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	if(state == used)
	    cluster_num = aux_cluster_num;
	
	i++;
	
    }
    
    //Si de una llega un offset mayor al tamaÃ±o del archivo, tengo que aumentar la cantidad de clusters y llenar todo con ceros
    while(state == last && i < aux_offset_int)
    {
	getFreeCluster(freeClusters, &free_cluster_num);
	setUsedCluster(freeClusters, 0x00000000 + free_cluster_num, cluster_num);
	cluster_num = free_cluster_num;
	
	createNullCluster(&(listSectors));
// 	truncateCluster(listSectors, 0);
	increaseCluster(listSectors, 0, boot->cluster_size);
	
	writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
	*wrote = *wrote + boot->cluster_size;
	
	setUsedCluster(freeClusters, 0x0FFFFFF8, cluster_num);
	
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt = NULL;
    }
    
    if (state == last && aux_offset_int > 0)
    {
	getFreeCluster(freeClusters, &free_cluster_num);
	setUsedCluster(freeClusters, 0x00000000 + free_cluster_num, cluster_num);
	cluster_num = free_cluster_num;
	setUsedCluster(freeClusters, 0x0FFFFFF8, cluster_num);
    }

    
    if(i == aux_offset_int)
    { 
	while(i <= total_clusters_int)
	{
	    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	    
	    if (state == last)
	    {
		if(i == total_clusters_int)
		    registry = 0x0FFFFFF8;
		else 
		{
		    getFreeCluster(freeClusters, &free_cluster_num);
		    registry = 0x00000000 + free_cluster_num;
		}
	    }
	    
	    
	    if(i == total_clusters_int)
		aux_size = total_clusters_mod;
	    else 
		aux_size = boot->cluster_size;
	    
// 	    if(aux_offset_mod > 0 || aux_size < boot->cluster_size)
// 		readClusterNIPC(disk, boot, cluster_num, 0, boot->cluster_size, listSectors);
	    
	    char *aux_content = (char *) malloc(sizeof(char) * aux_size);
// 	    strncpy(aux_content, content, aux_size);
	    memcpy(aux_content, content, aux_size);
	    
	    charToListSectors(aux_content, old_size, i, aux_offset_mod, aux_size, &listSectors);

	    if (state == last)
	    {
		setUsedCluster(freeClusters, registry, cluster_num);
		if(i != total_clusters_int)
		    cluster_num = free_cluster_num;
	    }
	    
// 	    writeCluster(disk, boot, cluster_num + aux_offset_int  + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
// 	    writeCluster(disk, boot, cluster_num + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
	    writeClusterIntoCache(disk, boot, path, cluster_num + boot->first_data_cluster - 2, aux_offset_mod, aux_size, listSectors);
	    *wrote = *wrote + (aux_size - aux_offset_mod);
	    
	    listSectors = (sectors *) malloc(sizeof(sectors));
	    listSectors->data = NULL;
	    listSectors->sgt = NULL;
	
	    aux_offset_mod = 0;
	    i++;
	    
	}
	
    }
    else
	return -ENOENT;
    
    return 1;

}


int hotfat_write(const char* path, const char* buf, size_t size, off_t offset, struct fuse_file_info* fi)
{
    size_t len;
    (void) fi;
    
    int flag = 0;
    unsigned int wrote = 0;
    
	if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0)
	{
        if(strcmp(path, "/") == 0) {
// 	    aux_size = 0;
		}
		else
		{
			directory *q = (directory *) malloc(sizeof(directory));
			searchDirectory(path,root,&q);
			unsigned int free_cluster_num;
			if(q->data->type == 32)
			{
				if(size > 0)
				{
					if(q->data->idCluster == 0)
					{
					    getFreeCluster(freeClusters, &free_cluster_num);
					    q->data->idCluster = free_cluster_num;
					    setUsedCluster(freeClusters, 0x0FFFFFF8, q->data->idCluster);
					}
						
					
					
					writeFileFromLinkedClusters(disk, boot, path, fatTablePointer, q->data->idCluster, q->data->size, offset, size, buf, &wrote);
					
					if((offset + size) > q->data->size)
					    q->data->size = offset + size;
					
					if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
					    printf("pthread_mutex_lock\n");
					    exit(EXIT_FAILURE);
					}
					
					cacheFiles *w = fileDescriptorsTable;
					while(w != NULL && w->data != NULL && strcmp(w->data->path, path))
					    w = w->sgt;
					
					if(w != NULL && w->data != NULL)
					{
					    if(w->data->cant_opens > 0)
					    {
	    // 				    if(offset == 0) //Se cambio la forma de verificar si es el primer ingreso
	    // 					pthread_mutex_lock(&(w->data->write_mutex));
	    // 					sem_wait(&(w->data->write_semaphore));
						    
	    // 				  	w->data->wrote = w->data->wrote + wrote;
						w->data->change_size = 1;
						w->data->wrote = wrote + offset;
						w->data->release_size = 1;
					    }
					}
						
					if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
					    printf("pthread_mutex_lock\n");
					    exit(EXIT_FAILURE);
					}
					
// 					saveFAT(disk, boot, fatTablePointer);
				}
			}
		}
    }
    
    return size;
    
}


int charToListSectors(char *buf, unsigned int old_size, int cluster_of_file, unsigned int offset, unsigned int size, sectors **listSectors)
{
    sector *aux_sec;
    aux_sec = (sector *) malloc(sizeof(sector));
    aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0, wrote = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    while(i < div_sectors_int)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	increaseSector(&(aux_sec->sec), 0, boot->bytes_per_sector);
	addToList((gl *)(*listSectors),aux_sec);
	i++;
    }
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	if(div_sectors_resto > 0)
	{
	    if((cluster_of_file * boot->cluster_size) < old_size)
		readSector(disk, boot, i, 0, boot->bytes_per_sector, &(aux_sec->sec));
	    else
		increaseSector(&(aux_sec->sec), 0, div_sectors_resto);
	}
	
	memcpy((aux_sec->sec),(buf+wrote),aux_size-div_sectors_resto);
	
	if(aux_size < boot->bytes_per_sector)
	    truncateSector(&(aux_sec->sec), aux_size);
// 	    increaseSector(&(aux_sec->sec), aux_size, boot->bytes_per_sector);
	
// 	fillWithChar(&(aux_sec->sec), ' ', boot->bytes_per_sector);
	
	addToList((gl *)(*listSectors),aux_sec);
	
 	wrote = wrote + aux_size - div_sectors_resto;
	
	div_sectors_resto = 0;
	i++;
    }
    
    
    while(i<boot->sectors_per_cluster)
    {
	aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
// 	increaseSector(&(aux_sec->sec), 0, boot->bytes_per_sector);
	truncateSector(&(aux_sec->sec), 0);
	addToList((gl *)(*listSectors),aux_sec);
	i++;
    }
    
    
    return 1;
}


int createCacheFile(const char *path, int fi_flags)
{
    int ret = 1;
    cacheFile *file;
    
    
    if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    
    cacheFiles *q = fileDescriptorsTable;
    
    while(q != NULL && q->data != NULL && strcmp(q->data->path, path))
	q = q->sgt;
    
    if(q != NULL && q->data != NULL)
    {
	if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	    if(pthread_mutex_trylock(&(q->data->write_mutex))) //Si se abre para write, blockeo el mutex
		q->data->cant_opens = q->data->cant_opens + 1;
	    else
		ret = -1;
	
    }
    else
    {
	file = (cacheFile *) malloc (sizeof(cacheFile));
        
// 	if( sem_init( &file->write_semaphore, 0, 1) == -1 ){
//                 free(file);
//                 return NULL;
//         }
        
//         file->write_mutex = ;
// 	pthread_mutex_t a;
// 	file->write_mutex = a;//PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_init(&(file->write_mutex), NULL);
	if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	    pthread_mutex_lock(&(file->write_mutex));//Si se abre para write, blockeo el mutex
	
	file->path = (char *) malloc (sizeof(char) * 256);
	strcpy(file->path,path);
	file->cant_opens = 1;
	file->wrote = 0;
	file->change_size = 0;
	file->release_size = 0;
	file->cache_first = NULL;
	file->cache_last = NULL;
	
	int i;
	if(cache_enabled)
	{
	    for(i=0;i<cant_cache_clusters;i++)
	    {
		cacheClusters *new_node = (cacheClusters *) malloc (sizeof(cacheClusters));
		new_node->data = (cacheCluster *) malloc (sizeof(cacheCluster));
		new_node->data->cluster_data = (cluster *) malloc (sizeof(cluster));
		new_node->data->cluster_data->data = NULL;
		new_node->data->cluster_data->sgt = NULL;
		new_node->data->cluster_num = 0;
		new_node->data->wrote = 0;
		new_node->ant= NULL;
		new_node->sgt=NULL;
		
		addToDobleList((gdl **) &(file->cache_first), (gdl **)&(file->cache_last), (gdl **)&(new_node));
	    }
	}   
	
        addToList((gl *)fileDescriptorsTable,file);
	
    }
    
    if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    
    return ret;
}


int readClusterFromCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    if(cache_enabled)
    {
	unsigned int cache_pos, read = 0;
	
	if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}
	
	cacheFiles *cf = fileDescriptorsTable;
		    
	while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
	    cf = cf->sgt;
	
	if(cf != NULL && cf->data != NULL)
	{   
	    cacheClusters *aux_cf = cf->data->cache_first;
	    while(aux_cf != NULL)
	    {
		if(aux_cf->data != NULL && aux_cf->data->cluster_num == num_cluster)
		{
		    //Leo el cluster que necesito de la cache
		    readCacheCluster(aux_cf->data->cluster_data, offset, size, listSectors);
		    bringToFrontOfDobleList((gdl **) &(cf->data->cache_first), (gdl **)&(cf->data->cache_last), (gdl **)&(aux_cf));
		    read = 1;
		    break;
		}
		aux_cf = aux_cf->sgt;
	    }
		
		
	    if(read == 0)
	    {
		aux_cf = cf->data->cache_last;
		
		if(aux_cf->data != NULL && aux_cf->data->cluster_data != NULL && aux_cf->data->cluster_data->data != NULL && aux_cf->data->cluster_data->data->sec != NULL)
		{
		    if(aux_cf->data->cluster_num != 0)
		    {
			writeClusterNIPC(disk, boot, aux_cf->data->cluster_num, 0, boot->cluster_size, aux_cf->data->cluster_data);
			//Limpio el registro de cache
			aux_cf->data->cluster_data = (cluster *) malloc(sizeof(cluster));
			aux_cf->data->cluster_data->data = NULL;
			aux_cf->data->cluster_data->sgt = NULL;
			aux_cf->data->cluster_num = 0;
			aux_cf->data->wrote = 0;
// 			createNullCluster(&(aux_cf->data->cluster_data));
		    }
// 		    else
// 			truncateCluster(&(aux_cf->data->cluster_data), 0);
		}
// 		else
// 		    createNullCluster(&(aux_cf->data->cluster_data));
		
		readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, (sectors *)aux_cf->data->cluster_data);
		aux_cf->data->cluster_num = num_cluster;
		bringToFrontOfDobleList((gdl **) &(cf->data->cache_first), (gdl **)&(cf->data->cache_last), (gdl **)&(aux_cf));
		
		readCacheCluster(aux_cf->data->cluster_data, offset, size, listSectors);
		
	    }
	}
	else	
	    readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
	
	if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}
    }
    else
	readClusterNIPC(disk, boot, num_cluster, offset, size, listSectors);
    

    return 1;
}


int readCacheCluster(cluster *cluster_data, unsigned int offset, unsigned int size, sectors *listSectors)
{
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size, i = 0;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    cluster *q = cluster_data;

    while(i < div_sectors_int)
	q = q->sgt;
	
    while(i<boot->sectors_per_cluster && i<= div_total_size_int)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	sector *aux_sec = (sector *) malloc(sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * (aux_size - div_sectors_resto));
	memcpy((aux_sec->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
	
	addToList((gl *)listSectors,aux_sec);
	div_sectors_resto = 0;
	q = q->sgt;
	i++;
    }
    
    return 1;
}

int writeClusterIntoCache(FILE* disk, bootRegion* boot, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    if(cache_enabled)
    {
	unsigned int cache_pos, wrote = 0;
	
	if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}
	
	cacheFiles *cf = fileDescriptorsTable;
		    
	while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
	    cf = cf->sgt;
	
	if(cf != NULL && cf->data != NULL)
	{   
	    
	    cacheClusters *aux_cf = cf->data->cache_first;
	    while(aux_cf != NULL)
	    {
		if(aux_cf->data != NULL && aux_cf->data->cluster_num == num_cluster)
		{
		    writeCacheCluster(&(aux_cf->data->cluster_data), path, num_cluster, offset, size, listSectors);
		    aux_cf->data->wrote = 1;
		    bringToFrontOfDobleList((gdl **) &(cf->data->cache_first), (gdl **)&(cf->data->cache_last), (gdl **)&(aux_cf));
		    wrote = 1;
		    break;
		}
		aux_cf = aux_cf->sgt;
	    }
	    
	    if(wrote == 0)
	    {
		
		aux_cf = cf->data->cache_last;
		
		if(aux_cf->data != NULL && aux_cf->data->cluster_data != NULL && aux_cf->data->cluster_data->data != NULL && aux_cf->data->cluster_data->data->sec != NULL)
		{
		    if(aux_cf->data->cluster_num != 0)
		    {
			writeClusterNIPC(disk, boot, aux_cf->data->cluster_num, 0, boot->cluster_size, aux_cf->data->cluster_data);
			//Limpio el registro de cache
			aux_cf->data->cluster_data = (cluster *) malloc(sizeof(cluster));
			aux_cf->data->cluster_data->data = NULL;
			aux_cf->data->cluster_data->sgt = NULL;
			aux_cf->data->cluster_num = 0;
			aux_cf->data->wrote = 0;
// 			createNullCluster(&(aux_cf->data->cluster_data));
		    }
// 		    else
// 			truncateCluster(&(aux_cf->data->cluster_data), 0);
		}
// 		else
// 		    createNullCluster(&(aux_cf->data->cluster_data));
		
		//Lo traigo a cache
		readClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, aux_cf->data->cluster_data);
		aux_cf->data->cluster_num = num_cluster;
		bringToFrontOfDobleList((gdl **) &(cf->data->cache_first), (gdl **)&(cf->data->cache_last), (gdl **)&(aux_cf));
		
		//Modifico el cluster en cuestion
		writeCacheCluster(&(aux_cf->data->cluster_data), path, num_cluster, offset, size, listSectors);
		aux_cf->data->wrote = 1;
		
	    }
	}
	
	if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}
    }
    else
	writeClusterNIPC(disk, boot, num_cluster, 0, boot->cluster_size, listSectors);

    return 1;
}


int writeCacheCluster(cluster **cluster_data, const char *path, unsigned int num_cluster, unsigned int offset, unsigned int size, sectors* listSectors)
{
    sectors *aux_sec;
    int i;
    unsigned int div_sectors_int, div_sectors_resto, div_total_size_int, div_total_size_resto, aux_size;
        
    div_sectors_int = offset / boot->bytes_per_sector;
    div_sectors_resto = offset % boot->bytes_per_sector;
    
    div_total_size_int = size / boot->bytes_per_sector;
    div_total_size_resto = size % boot->bytes_per_sector;
    
    if(div_total_size_int > 0 && div_total_size_resto == 0)
    {
	div_total_size_resto = boot->bytes_per_sector;
	div_total_size_int--;
    }
    
    sectors *q = listSectors;
    sectors *aux_cache = *cluster_data;
    
    for(i=0;i< div_sectors_int && q != NULL;i++)
    {
	q = q->sgt;
	aux_cache = aux_cache->sgt;
    }
    
    while(i<boot->sectors_per_cluster && i<= div_total_size_int && q != NULL)
    {
	if(i == div_total_size_int)
	    aux_size = div_total_size_resto;
	else
	    aux_size = boot->bytes_per_sector;
	
	memcpy((aux_cache->data->sec),(q->data->sec+div_sectors_resto),aux_size-div_sectors_resto);
	
	div_sectors_resto = 0;
	q = q->sgt;
	aux_cache = aux_cache->sgt;
	i++;
    }
    
    return 1;
}

int createNullCluster(sectors **listSectors)
{
    unsigned int i = 0;
        
    while(i< boot->sectors_per_cluster)
    {
	sector *aux_sec = (sector *) malloc (sizeof(sector));
	aux_sec->sec = (char *) malloc (sizeof(char) * boot->bytes_per_sector);
	
	truncateSector(&(aux_sec->sec), 0);
	addToList((gl *)*listSectors,aux_sec);
	i++;
    }
    
    return 1;
}

int flushCache(const char *path)
{
    unsigned int cache_pos;

    if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
	
    cacheFiles *cf = fileDescriptorsTable;
		
    while(cf != NULL && cf->data != NULL && strcmp(cf->data->path, path))
	cf = cf->sgt;
    
    if(cf != NULL && cf->data != NULL)
    {   
// 	for(cache_pos = 0; cache_pos < cant_cache_clusters ; cache_pos++)
// 	{
// 	    if(cache[cache_pos].cluster_data->data != NULL && cache[cache_pos].file_path != NULL && !strcmp(cache[cache_pos].file_path, path))
// 	    {
// 		//Escribo el cluster que no fue escrito
// 		writeClusterNIPC(disk, boot, cache[cache_pos].cluster_num, 0, boot->cluster_size, cache[cache_pos].cluster_data);
// 		//Limpio el registro de cache
// 		cache[cache_pos].cluster_data->data = NULL;
// 		cache[cache_pos].cluster_data->sgt = NULL;
// 		strcpy(cache[cache_pos].file_path, "/");
// 		createNullCluster(&(cache[cache_pos].cluster_data));
// 		
// 		cache[cache_pos].cluster_num = 0;
// 	    }
// 	}
    }
    
    if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }

    return 1;
}


int hotfat_flush(const char *path, struct fuse_file_info *fi)
{
    
//     flushCache(path);
    
    return 0;
}


int hotfat_release(const char *path, struct fuse_file_info *fi)
{
    
//     fsinfo();
//     finfo(path);

    if(releaseCacheFile(path, fi->flags))
	return 0;
    else
	return 1;
}


int releaseCacheFile(const char *path, int fi_flags){

    int ret = 1;
    
//     cacheDump(11);
    
    if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    
    cacheFiles *q = fileDescriptorsTable;
    
    while(q != NULL && q->data != NULL && strcmp(q->data->path, path))
	q = q->sgt;
    
    if(q != NULL && q->data != NULL)
    {
	if ((fi_flags & O_WRONLY) == O_WRONLY || (fi_flags & O_RDWR) == O_RDWR)
	{
	    
	    directory *p = (directory *) malloc(sizeof(directory));
	    searchDirectory(path,root,&p);
	    if(p->data->type == 32)
	    {
		//Save wrote as new size
		if(q->data->change_size == 1)
		{
		    p->data->size = q->data->wrote;
		    saveFAT(disk, boot, fatTablePointer);
		}
		
		if(q->data->release_size == 1)
		{
		    char *aux_direct = (char *) malloc(sizeof(char) * 32+1);
		    createDirectoryInput(&aux_direct, p->data);
		    
		    //Buscar dir padre
		    char *pathFather = (char *) malloc(sizeof(char)*256);
		    fatherName(path,pathFather);
		    directory *direc = (directory *) malloc(sizeof(directory));
		    searchDirectory(pathFather,root,&direc);
		    
		    pthread_mutex_lock(&(direc->data->dir_mutex));
		    if(saveDirectoryInputIntoLinkedClusters(direc->data->idCluster, aux_direct, 2))
		    {
			pthread_mutex_unlock(&(direc->data->dir_mutex));
			free(aux_direct);
		    }
		    else
		    {
			pthread_mutex_unlock(&(direc->data->dir_mutex));
			free(aux_direct);
			q->data->change_size = 0;
			q->data->release_size = 0;
			
			
			pthread_mutex_unlock(&(q->data->write_mutex));
			if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
			    printf("pthread_mutex_lock\n");
			    exit(EXIT_FAILURE);
			}
			return -1;
		    }
		}
		q->data->change_size = 0;
		q->data->release_size = 0;
		
		
		pthread_mutex_unlock(&(q->data->write_mutex));
		
	    }

	}
	    
	    
    }
    else
    {
	if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}
	return 0;
    }

    if(q->data->cant_opens > 1)
	q->data->cant_opens = q->data->cant_opens - 1;
    else
    {
	cacheFiles *aux_file = fileDescriptorsTable;
	if(aux_file != NULL && aux_file->sgt == NULL)
	{
	    fileDescriptorsTable = (cacheFiles *) malloc(sizeof(cacheFiles));
	    fileDescriptorsTable->data = NULL;
	    fileDescriptorsTable->sgt = NULL;
	    releaseCacheData(aux_file->data);
	    pthread_mutex_destroy(&(aux_file->data->write_mutex));
	    free(aux_file->data->path);
	    free(aux_file->data);
	    free(aux_file);
	}
	else if(aux_file != NULL && aux_file->sgt != NULL)
	{
	    if(aux_file != NULL && aux_file->data != NULL && !strcmp(aux_file->data->path, q->data->path))
	    {
		fileDescriptorsTable = q->sgt;
		releaseCacheData(q->data);
		pthread_mutex_destroy(&(q->data->write_mutex));
		free(q->data->path);
		free(q->data);
		free(q);
	    }
	    else
	    {
		while(aux_file->sgt != NULL && aux_file->sgt->data != NULL && strcmp(aux_file->sgt->data->path, q->data->path))
		    aux_file = aux_file->sgt;
	
		if(aux_file->sgt != NULL && aux_file->sgt->data != NULL && !strcmp(aux_file->sgt->data->path, q->data->path))
		{
		    aux_file->sgt = q->sgt;
		    releaseCacheData(q->data);
		    pthread_mutex_destroy(&(aux_file->data->write_mutex));
		    free(q->data->path);
		    free(q->data);
		    free(q);
		}
	    }
	}
	else
	    ret = 0;
    }
    
    if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    

    
    return ret;
}


int releaseCacheData(cacheFile *file)
{

    if(cache_enabled)
    {
	while(file->cache_first != NULL)
	{
	    cacheClusters *aux_free = file->cache_first;

	    if(file->cache_last == aux_free)
	    {
		file->cache_last = NULL;
		file->cache_first = NULL;
	    }
	    else
	    {
		aux_free->sgt->ant = NULL;
	    	file->cache_first = aux_free->sgt;
	    }

	    aux_free->ant = NULL;
	    aux_free->sgt = NULL;

	    if(aux_free->data != NULL)
	    {    
		if(aux_free->data->cluster_data != NULL && aux_free->data->cluster_data->data != NULL && aux_free->data->cluster_data->data->sec != NULL)
		{
		    if(aux_free->data->cluster_num != 0 && aux_free->data->wrote == 1)
		    {    
			writeClusterNIPC(disk, boot, aux_free->data->cluster_num, 0, boot->cluster_size, aux_free->data->cluster_data);
// 			aux_free->data->cluster_data = (cluster *) malloc(sizeof(cluster));
// 			aux_free->data->cluster_data->data = NULL;
// 			aux_free->data->cluster_data->sgt = NULL;
			aux_free->data->cluster_num = 0;
			aux_free->data->wrote = 0;
		    }
		    
// 		    free(aux_free->data->cluster_data);
		}
		free(aux_free->data);
	    }
	    free(aux_free);
	}
	
    }
    
    return 1;
}

int saveDirectoryInputIntoSector(char **data_sector, char *new_dir_input, unsigned int mode)
{
    //mode == 1: new input
    //mode == 2: update input
    //mode == 3: delete input
    //mode == 4: delete long name input
    
    int j,z;
    directoryInput *dir = (directoryInput *) malloc(sizeof(directoryInput));
    
    for(j=0;j< boot->bytes_per_sector;j+=32)
    {
		if((*data_sector)[j] == 0 && mode == 1)
		{
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
		
		if(!strncmp((*data_sector) +j, new_dir_input, 11) && mode == 2)
		{
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
		
		if(!strncmp((*data_sector) +j, new_dir_input, 11) && mode == 3)
		{
			*new_dir_input = '\345';
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
		
		if(!strncmp((*data_sector) +j, new_dir_input, 32) && mode == 4)
		{
			*new_dir_input = '\345';
			memcpy((*data_sector) +j,new_dir_input,32);
			return 1;
		}
    }
    
    return 0;
} 

int saveDirectoryInputIntoCluster(cluster *dirCluster, char *new_dir_input, unsigned int mode)
{
    cluster *q = dirCluster; 
    
    while (q != NULL && q->data != NULL && q->data->sec != NULL)
    {
	if(saveDirectoryInputIntoSector(&(q->data->sec), new_dir_input, mode))
	    return 1;
	
	q = q->sgt;
    }
    
    return 0;
}

int saveDirectoryInputIntoLinkedClusters(unsigned int cluster_num, char *new_dir_input, unsigned int mode)
{
    //mode == 1: new input
    //mode == 2: update input
    
    enum cluster_state state;
    sectors *listSectors;
    
    unsigned int aux_cluster_num, registry, free_cluster_num;

    unsigned int aux_cache_enabled = cache_enabled;
    cache_enabled = 0;
    
    do
    {
	listSectors = (sectors *) malloc(sizeof(sectors));
	listSectors->data = NULL;
	listSectors->sgt = NULL;
	
	readClusterFromCache(disk, boot, "", cluster_num + boot->first_data_cluster  - 2, 0, boot->cluster_size, listSectors);
	if(saveDirectoryInputIntoCluster((cluster *)listSectors, new_dir_input, mode))
	{
	    writeClusterIntoCache(disk, boot, "", cluster_num + boot->first_data_cluster  - 2, 0, boot->cluster_size, listSectors);
	    cache_enabled = aux_cache_enabled;
	    return 1;
	}
	
	getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	
	if(state == used)
	    cluster_num = aux_cluster_num;
	
	if (state == last)
	{
	    getFreeCluster(freeClusters, &free_cluster_num);
	    registry = 0x00000000 + free_cluster_num;
	    
	    setUsedCluster(freeClusters, registry, cluster_num);
	    cluster_num = free_cluster_num;
	    
	    setUsedCluster(freeClusters, 0x0fffffff, cluster_num);
	    
	    sectors * auxListSectors = (sectors *) malloc(sizeof(sectors));
	    auxListSectors->data = NULL;
	    auxListSectors->sgt = NULL;
	
	    createNullCluster(&auxListSectors);
	    writeClusterIntoCache(disk, boot, "", cluster_num + boot->first_data_cluster - 2, 0, boot->cluster_size, auxListSectors);
	    
	    mode = 1; 
	    state = used;
	}
	
    } while(state == used);
    
    cache_enabled = aux_cache_enabled;
    
    return 0;
    
    

}

int hotfat_mkdir(const char *path, mode_t mode)
{
    unsigned int free_cluster_num;
   	char *name = (char *) malloc (sizeof(char) * 14);
    directoryInput *new_input = (directoryInput *) malloc (sizeof(directoryInput));
//     new_input->name = (char *) malloc (sizeof(char) * 9);
//     new_input->ext = (char *) malloc (sizeof(char) * 4);
// 	new_input->longName = (char *) malloc(sizeof(char)*14);
	
	//newName(path,new_input->name);
//     strcpy(new_input->name,path+1);
    
	newName(path,name);
	//strcpy(new_input->name,name);
	if(strlen(name)<=8)
	{
		//memcpy(new_input->name,name,strlen(name)+1);
		//memset(new_input->name+strlen(name),'\0',1);
		strcpy(new_input->name,name);
		strcpy(new_input->longName,"null");
	}
	else
	{
		//memcpy(new_input->name,name,8);
		//memcpy(new_input->name,"\0",1);
// 		strncpy(new_input->name,name,8);


// 		memset(new_input->name,'\0',9);
// 		memcpy(new_input->name,name,8);
		memset(new_input->name, '\0', 9);
		memcpy(new_input->name,name,8);
		memset(new_input->longName,'\0',14);
		//strcpy(new_input->longName,"");
		memcpy(new_input->longName,name,13);
// 		memcpy(new_input->longName,name,13);
		
		
		//memcpy(new_input->longName,name , strlen(name)+1);
	}

    new_input->size = boot->cluster_size;
    new_input->type = 16;
    pthread_mutex_init(&(new_input->dir_mutex), NULL);
    
    
	//free(name);
	
// 	new_input->ext = "";
	strcpy(new_input->ext, "   ");
    
    getFreeCluster(freeClusters, &free_cluster_num);
    new_input->idCluster = free_cluster_num;
     
    sectors *listSectors = (sectors *) malloc(sizeof(sectors));
    listSectors->data = NULL;
    listSectors->sgt = NULL;
    
    createNullCluster(&(listSectors));
    truncateCluster(&listSectors, 0);
    writeClusterIntoCache(disk, boot, path, new_input->idCluster + boot->first_data_cluster - 2, 0, boot->cluster_size, listSectors);
    setUsedCluster(freeClusters, 0x0FFFFFF8, new_input->idCluster);
    
//     new_input->idCluster = 0;
    
    //Buscar dir padre
	char *pathFather = (char *) malloc(sizeof(char)*256);
	fatherName(path,pathFather);
    directory *q;// = (directory *) malloc(sizeof(directory));
    searchDirectory(pathFather,root,&q);
	//free(pathFather);
    if(strcmp(new_input->longName,"null"))
    {
	char *aux_longDirect = (char *) malloc(sizeof(char) * (32+1));
	createLongNameInput(&aux_longDirect,new_input);
	pthread_mutex_lock(&(q->data->dir_mutex));
	saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_longDirect, 1);
	pthread_mutex_unlock(&(q->data->dir_mutex));
	free(aux_longDirect);
    }
    
    char *aux_direct = (char *) malloc(sizeof(char) * (32+1));
    createDirectoryInput(&aux_direct, new_input);
    pthread_mutex_lock(&(q->data->dir_mutex));
    if(saveDirectoryInputIntoLinkedClusters(q->data->idCluster, aux_direct, 1))
    {
	pthread_mutex_unlock(&(q->data->dir_mutex));
	if(q->content == NULL)
	{
		q->content = (directory *) malloc(sizeof(directory));
		q->content->data = NULL;
		q->content->content = NULL;
		q->content->sgt = NULL;
	}
	addToListWithSublist((glws *)q->content, new_input, NULL);
	
	saveFAT(disk, boot, fatTablePointer);

	free(aux_direct);
	free(name);
	free(pathFather);
	return 0;
    }
    else
    {
	pthread_mutex_unlock(&(q->data->dir_mutex));
	free(aux_direct);
	free(name);
	free(pathFather);
	free(new_input);
	return -1;
    }

    return -1;
}

// void cacheDump(int signal)
// {
//     FILE* file_dump;
//     if ((file_dump = fopen("/home/utn_so/cache_dump.txt", "ab")) == NULL) {
// 	    return;
//     }
//     
//     if(cache_enabled)
//     {	    
// 	fprintf(file_dump, "-------- HOTFAT's CACHE DUMP --------\n");
// 	
// 	fprintf(file_dump, "-- Bloque: %d KB\n", boot->cluster_size / 1024 );
// 	fprintf(file_dump, "-- Cantidad de Bloques en cache: %u \n", cant_cache_clusters);
// 	
// 			
// 	if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
// 	    printf("pthread_mutex_lock\n");
// 	    exit(EXIT_FAILURE);
// 	}		
// 	cacheFiles *q = fileDescriptorsTable;
// 	unsigned int cache_pos = 0, clus = 0, sect = 0, byte = 0;
// 	
// 	while(q != NULL)
// 	{
// 	    fprintf(file_dump, "- Archivo: %s \n", cache[cache_pos].file_path);
// 	    
// 	    for(cache_pos = 0; cache_pos < cant_cache_clusters; cache_pos++)
// 	    {
// 		if(cache[cache_pos].file_path != NULL && !strcmp(cache[cache_pos].file_path, q->data->path))
// 		{
// 		    fprintf(file_dump, "-- Cluster: %u \n", cache[cache_pos].cluster_num);
// 		    fprintf(file_dump, "---- Content: \n");
// 		    sect=0;
// 		    cluster *sector_data = cache[cache_pos].cluster_data;
// 		    while(sect< boot->sectors_per_cluster && sector_data != NULL)
// 		    {
// 			for(byte=0;byte<boot->bytes_per_sector && sector_data->data->sec != NULL ;byte++)
// 			    printf("%c",(int) (sector_data->data->sec + byte));
// 			
// 			sector_data = sector_data->sgt;
// 			sect++;
// 		    }
// 		}
// 	    }
// 	    fprintf(file_dump, "--- ***************************** ---\n\n");
// 	    
// 	    q = q->sgt;
// 	}
// 		
// 	if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
// 	    printf("pthread_mutex_lock\n");
// 	    exit(EXIT_FAILURE);
// 	}
// 	fprintf(file_dump, "------ CACHE DUMP FINISH -------\n");
//     }
//     fclose(file_dump);
//     return;
// } 
    
void cacheDump(int signal)
{
    FILE* file_dump;
    if ((file_dump = fopen("../cache_dump.txt", "a")) == NULL) {
	    return;
    }
        
    fprintf(file_dump, "-------- HOTFAT's CACHE DUMP --------\n");
    
    if(pthread_mutex_lock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    cacheFiles *q = fileDescriptorsTable;
    unsigned int clus = 0, sect = 0, byte = 0;
    
    while(q != NULL && q->data != NULL)
    {
	if(q->data->cache_first != NULL)
	{
	    fprintf(file_dump, "- Archivo: %s \n", q->data->path);
	    
	    cacheClusters *aux_cc = q->data->cache_first;
	    
	    fprintf(file_dump, "-- Tamaño de Bloque de Cache: %d KB\n", boot->cluster_size / 1024 );
	    fprintf(file_dump, "-- Cantidad de Bloques en Cache: %i \n", cantClustersCache(aux_cc));
	    
	    clus = 0;
	    while(aux_cc != NULL)
	    {
		if(aux_cc->data != NULL && aux_cc->data->cluster_data != NULL && aux_cc->data->cluster_num !=0)
		{
		    cluster *sector_data = aux_cc->data->cluster_data;
		    clus++;
		    fprintf(file_dump, "\n-- Contenido de Bloque de Cache: %u \n", clus);
		    sect = 0;
		    while(sect< boot->sectors_per_cluster && sector_data != NULL && sector_data->data != NULL )
		    {
			if(sector_data->data->sec != NULL)
			    fprintf(file_dump, "%s", sector_data->data->sec);
// 			    for(byte=0;byte<boot->bytes_per_sector;byte++)
// 				fprintf(file_dump, "%c", (sector_data->data->sec + byte));
			
			sector_data = sector_data->sgt;
			sect++;
		    }  
		
		}
		
		aux_cc = aux_cc->sgt; 
		
	    }
	    
	    fprintf(file_dump, "\n--- ***************************** ---\n\n");
	    
	}
	q = q->sgt;
    }    
    
    if(pthread_mutex_unlock(&mutex_descriptors_table)!=0){
	printf("pthread_mutex_lock\n");
	exit(EXIT_FAILURE);
    }
    
    fprintf(file_dump, "\n-------------------------------------\n");
    fclose(file_dump);
    return;
} 

int cantClustersCache(cacheClusters *pNodo) 
{
    int n=0;
    while (pNodo != NULL && pNodo->data != NULL && pNodo->data->cluster_num != 0) {  
	++n;
	pNodo = pNodo->sgt;
    }
    return n;
}




/*
void cacheDump(int signal)
{
    FILE* file_dump;
    if ((file_dump = fopen("/home/utn_so/cache_dump.txt", "ab")) == NULL) {
	    return;
    }
    
    if(cache_enabled)
    {	    
	fprintf(file_dump, "-------- HOTFAT's CACHE DUMP --------\n");
	
	fprintf(file_dump, "-- Bloque: %d KB\n", boot->cluster_size / 1024 );
	fprintf(file_dump, "-- Cantidad de Bloques en cache: %u \n", cant_cache_clusters);
	
	cacheFiles *q = fileDescriptorsTable;
	unsigned int cache_pos = 0, clus = 0, sect = 0, byte = 0;
	
	if(pthread_mutex_lock(&mutex_cache)!=0){
	    printf("pthread_mutex_lock\n");
	    exit(EXIT_FAILURE);
	}

	while(q != NULL)
	{
	    if(pthread_mutex_lock(&mutex_cache)!=0){
		printf("pthread_mutex_lock\n");
		exit(EXIT_FAILURE);
	    }
	    
	    fprintf(file_dump, "- Archivo: %s \n", cache[cache_pos].file_path);
	    
	    for(cache_pos = 0; cache_pos < cant_cache_clusters; cache_pos++)
	    {
		if(cache[cache_pos].file_path != NULL && !strcmp(cache[cache_pos].file_path, q->data->path))
		{
		    fprintf(file_dump, "-- Cluster: %u \n", cache[cache_pos].cluster_num);
		    fprintf(file_dump, "---- Content: \n");
		    sect=0;
		    cluster *sector_data = cache[cache_pos].cluster_data;
		    while(sect< boot->sectors_per_cluster && sector_data != NULL)
		    {
			for(byte=0;byte<boot->bytes_per_sector && sector_data->data->sec != NULL ;byte++)
			    printf("%c",sector_data->data->sec + byte);
			
			sector_data = sector_data->sgt;
			sect++;
		    }
		}
	    }
	    fprintf(file_dump, "--- ***************************** ---\n\n");
	    
	    q = q->sgt;
	}
	fprintf(file_dump, "------ CACHE DUMP FINISH -------\n");
    }
    fclose(file_dump);
    return;
} */


/*
void cacheDump(int signal)
{
    FILE* file_dump;
    if ((file_dump = fopen("cache_dump.txt", "a")) == NULL) {
	    return;
    }
        
    fprintf(file_dump, "-------- HOTFAT's CACHE DUMP --------\n");
    
    cacheFiles *q = fileDescriptorsTable;
    unsigned int cache_pos = 0, clus = 0, sect = 0, byte = 0;
    while(q != NULL)
    {
	fprintf(file_dump, "- Archivo: %s \n", q->data->path);
	

	    if(q->data->cache[cache_pos].cluster_data != NULL && q->data->cache[cache_pos].cluster_num != 0)
	    {
		fprintf(file_dump, "-- Bloque: %d KB\n", boot->cluster_size / 1024 );		
    fprintf(file_dump, "-- Cantidad de Bloques en cache: %u \n", cant_cache_clusters);
    	for(cache_pos = 0; cache_pos < cant_cache_clusters; cache_pos++)
	{
		fprintf(file_dump, "---- Content Bloque #%u: \n", cache_pos);
		sect=0;
		cluster *sector_data = q->data->cache[cache_pos].cluster_data;
		while(sect< boot->sectors_per_cluster && sector_data != NULL && sector_data->data != NULL )
		{
      if(sector_data->data->sec != NULL)
		    for(byte=0;byte<boot->bytes_per_sector;byte++)
           fprintf(file_dump, "%c", (int) (sector_data->data->sec + byte));
		    
		    sector_data = sector_data->sgt;
		    sect++;
		}     
      } 
      fprintf(file_dump, "--- ***************************** ---\n\n");
	    }

	
	q = q->sgt;
    }
    fprintf(file_dump, "-------------------------------------\n");
    fclose(file_dump);
    return;
} */


int searchPath(directory *dir, char* name, directory **result)
{
	if(strcmp(name, "") != 0)
	{
		//int lenght = (int)strlen(name);
		directory *p = dir;
		
		while (p != NULL && p->data != NULL)
		{
			if(strcmp(p->data->longName,"null") == 0)
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 9);
			    strcpy(nameWithOutSpaces, p->data->name);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			else
			{
			    char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 14);
			    strcpy(nameWithOutSpaces, p->data->longName);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    free(nameWithOutSpaces);
				    break;
			    }
			    free(nameWithOutSpaces);
			}
			
			p = p->sgt;
		} 
		if(*result != p)
			*result = NULL;
	}
	else 
		*result = dir;
    return 1;
}

int searchPath2(directory *dir, char* name, directory **result, directory **last)
{
	directory *auxlast = dir;
	int first = 0;
	char *nameWithOutSpaces = (char *) malloc(sizeof(char) * 18);
	
	if(strcmp(name, "") != 0)
	{
		int lenght = (int)strlen(name);
		directory *p = dir;
		
		while (p != NULL)
		{
			if(strcmp(p->data->longName,"null") == 0)
			{
			    strcpy(nameWithOutSpaces, p->data->name);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    *last = auxlast;
				    break;
			    }
			}
			else
			{
			    strcpy(nameWithOutSpaces, p->data->longName);
			    rtrimHOTFAT(nameWithOutSpaces,' ');
			    if((p->data->type == 16  || p->data->type == 32) && (!strncmp(nameWithOutSpaces,name,strlen(nameWithOutSpaces))))
			    {
				    *result=p;
				    *last = auxlast;
				    break;
			    }
			}
			
			if(first != 0)
			    auxlast = auxlast->sgt;
			else
			    first++;
			
			p = p->sgt;
		} 
		if(*result != p)
			*result = NULL;
		else 
		if(auxlast == p)
			*last = NULL;
	}
	else 
	{
		*result = dir;
		*last = NULL;
	}
	
	free(nameWithOutSpaces);
	return 1;
    
    
//     int lenght = (int)strlen(name);
// 	int first = 0;
//     directory *p = dir;
// 	directory *auxlast = dir;
//     while (p != NULL)
//     {
// 		if((p->data->type == 16  || p->data->type == 32) && (!strncmp(p->data->name,name,lenght)))
// 		{
// 			*result=p;
// 			*last = auxlast;
// 			break;
// 		}
// 		p = p->sgt;
// 		if(first)
// 			auxlast = auxlast->sgt;
// 		first++;
//     } 
// 
// 	if(*result != p)
// 		*result = NULL;
// 	else 
// 		if(auxlast == p)
// 			*last = NULL;
	
	
    return 1;
}

int cutPath(const char *path,char *directory[],int *count)
{
    int i;
    char *aux = (char *) malloc(sizeof(char)*9);
    strcpy(aux,path);
	*count = 1;
    directory[0] = strtok(aux,"/");
    for(i = 1; (directory[i]= strtok(NULL, "/"));i++,(*count)++);
    
    return 1;
}

int cutPath2(const char *path,char *directory,char* finalPath)
{
    char *aux = (char *) malloc(sizeof(char)*256);
    if(strlen(path)>1)
    {
	strcpy(aux,path);
	strcpy(directory,strtok(aux,"/"));
	strcpy(finalPath,path+(strlen(directory)+1));
    }
    else
    {
		strcpy(directory,"");
		strcpy(finalPath,path);
    }
		
    free(aux);
    return 1;
}

int cutPath3(const char *path,char *directory,char* finalPath)
{
	char *aux = (char *) malloc(sizeof(char)*256);
	strcpy(aux,path);
	//char **aux2;// = (char *) malloc(sizeof(char)*256);
	if(strlen(path)>1)
	{
		//strcpy(aux,path);
		//strcpy(directory,strtok(aux,"/"));
		//strcpy(finalPath,path+(strlen(directory)+1));
		
		strcpy(directory,strtok_r(aux,"/",&finalPath));
		//strcpy(finalPath,aux2);
	}
	else
	{
		strcpy(directory,"");
		strcpy(finalPath,path);
	}
	//free(aux2);
	free(aux);

    return 1;
}

int cutPath4(const char *path,char *directory,char** finalPath)
{
	char *aux = (char *) malloc(sizeof(char)*256);
	strcpy(aux,path);
	//char **aux2;// = (char *) malloc(sizeof(char)*256);
	if(strlen(path)>1)
	{
		//strcpy(aux,path);
		//strcpy(directory,strtok(aux,"/"));
		//strcpy(finalPath,path+(strlen(directory)+1));
		
		strcpy(directory,strtok_r(aux,"/",finalPath));
		//strcpy(finalPath,aux2);
	}
	else
	{
		strcpy(directory,"");
		strcpy(*finalPath,path);
	}
	//free(aux2);
	free(aux);

    return 1;
}

int newName(const char* path, char *name)
{
	char *primero = (char *) malloc(sizeof(char)*18);
	char *resto= (char *) malloc(sizeof(char)*256);

	cutPath2(path,primero,resto);
	while(strcmp(resto,"") != 0)
		cutPath2(resto,primero,resto);
	
	strcpy(name,primero);
	
	name = rtrimHOTFAT(name,'/');
	name = ltrimHOTFAT(name,'/');

	free(primero);
	free(resto);
	
	return 1;
}

int fatherName(const char *path,char *fatherPath)
{
	char *primero = (char *) malloc(sizeof(char)*14);
	char *resto= (char *) malloc(sizeof(char)*256);
	char *name= (char *) malloc(sizeof(char)*256);
			
	newName(path,name);

	cutPath2(path,primero,resto);
	if(strcmp(resto,"")!=0)
	{
		sprintf(fatherPath,"/%s",primero);
		while(strcmp(resto+1,name) != 0)
		{
			cutPath2(resto,primero,resto);
			sprintf(fatherPath,"%s/%s",fatherPath,primero);
		}
	}
	else
	{
		strcpy(fatherPath,"/");
	}
	
	free(primero);
	free(resto);
	free(name);
	
	
 	return 1;
}

int searchDirectory(const char* path, directory *root, directory **dir)
{
    if(strcmp(path,"/") != 0)
    {
	char *primero = (char *) malloc(sizeof(char)*18);
	char *resto= (char *) malloc(sizeof(char)*256);
	cutPath2(path,primero,resto);
	directory *content_search = root;

	int flag = 0;
	
	while(strcmp(resto,"") != 0 || flag < 1)
	{
	    searchPath(content_search->content,primero,&(*dir));
	    if(*dir == NULL)
		break;
	    content_search = *dir;
	    if(strcmp(resto,"") != 0)
		cutPath2(resto,primero,resto);
	    else
		flag++;
	}
	
	free(primero);
	free(resto);
    }
    else
	*dir = root;
    return 1;
}

int getDirectory(const char* path, directory *root, directory **dir)
{
	char *primero = (char *) malloc(sizeof(char)*18);
	char *resto= (char *) malloc(sizeof(char)*257);
	cutPath2(path,primero,resto);
	directory *last;// = (directory *) malloc(sizeof(directory));
	directory *content_search = root;
	int flag = 0;
	while(strcmp(resto,"") != 0 || flag < 1)
	{
		searchPath2(content_search->content,primero,&(*dir),&last);
		content_search = *dir;
		if(strcmp(resto,"") != 0)
			cutPath2(resto,primero,resto);
		else
			flag++;
	}
	
	if(last != NULL)
		last->sgt = (*dir)->sgt;
	else
	{
		char *fatherPath = (char *) malloc(sizeof(char) * 257);
		fatherName(path, fatherPath);
		directory *fatherDirectory;// = (directory *) malloc(sizeof(directory));
		searchDirectory(fatherPath, root, &fatherDirectory);
		free(fatherPath);
		pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		if((*dir)->sgt != NULL)
			fatherDirectory->content = (*dir)->sgt;
		else
			fatherDirectory->content = NULL;
		pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
	}

	free(primero);
	free(resto);
	return 1;
}

int youMakeMeFiller(directory *dir,void *buf, fuse_fill_dir_t *filler)
{
	char *nameWithoutSpace = (char *) malloc(sizeof(char)*18);
	if(strcmp(dir->data->longName,"null") == 0)
	{
	    strcpy(nameWithoutSpace, dir->data->name);
	    rtrimHOTFAT(nameWithoutSpace,' ');
	}
	else
	{
	    strcpy(nameWithoutSpace, dir->data->longName);
	    rtrimHOTFAT(nameWithoutSpace,' ');
	}
	if(dir->data->type == 16)
		(*filler)(buf,nameWithoutSpace,NULL,0);
	
	if(dir->data->type == 32)
	{
		if(strncmp(dir->data->ext,"   ",4) != 0 && strcmp(dir->data->ext,"") != 0)
		{
			char *fullName = (char *) malloc(sizeof(char)*21);
			char *extWithoutSpace = (char *) malloc(sizeof(char)*4);
			strcpy(extWithoutSpace, dir->data->ext);
			rtrimHOTFAT(extWithoutSpace,' ');
			sprintf(fullName,"%s.%s",nameWithoutSpace,extWithoutSpace);
			(*filler)(buf,fullName,NULL,0);
			
			free(extWithoutSpace);
			free(fullName);
		}
		else
			(*filler)(buf,nameWithoutSpace,NULL,0);
	}

	free(nameWithoutSpace);
	return 1;
}

int getAttrOfDir(directory *dir, const char *path,struct stat *stbuf)
{
	char *nameWithoutSpace = (char *) malloc(sizeof(char)*18);
	char *name = (char *) malloc(sizeof(char)*257);

	if(strcmp(dir->data->longName,"null") == 0)
	{
		strcpy(nameWithoutSpace, dir->data->name);
		rtrimHOTFAT(nameWithoutSpace,' ');
	}
	else
	{
		strcpy(nameWithoutSpace, dir->data->longName);
		nameWithoutSpace = rtrimHOTFAT(nameWithoutSpace,' ');
	}
	
	newName(path,name);
	if(strncmp(name,nameWithoutSpace,strlen(nameWithoutSpace)) == 0)
	{
		if(dir->data->type == 16)
		{
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
			stbuf->st_size =boot->cluster_size;
		}
		if(dir->data->type == 32)
		{
			stbuf->st_mode = S_IFREG | 0644;
			stbuf->st_nlink = 1;
			stbuf->st_size = dir->data->size;
		
		}
	}
	
	free(name);
	free(nameWithoutSpace);

	return 1;
}

char* rtrimHOTFAT(char* string, char junk)
{
    char* original = string + strlen(string);
    while(*--original == junk);
    *(original + 1) = '\0';
    return string;
}

char* ltrimHOTFAT(char *string, char junk)
{
    char* original = string;
    char *p = original;
    int trimmed = 0;
    do
    {
        if (*original != junk || trimmed)
        {
            trimmed = 1;
            *p++ = *original;
        }
    }
    while (*original++ != '\0');
    return string;
}

int hotfat_rmdir(const char* path)
{
	directory *dir = (directory *) malloc(sizeof(directory));

	searchDirectory(path,root,&dir);
	pthread_mutex_lock(&(dir->data->dir_mutex));
	
	if(dir->content == NULL)
	{
	    enum cluster_state state;
	    unsigned int cluster_num, aux_cluster_num;
	    
	    if(dir->data->idCluster != 0)
	    {
		cluster_num = dir->data->idCluster;
		do
		{
		    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
		    setFreeCluster(freeClusters, cluster_num);
		    cluster_num = aux_cluster_num;
		    
		} while(state == used);
	    }
	    
	    directory *q = dir->content;
	    
	    while(q != NULL && q->data != NULL)
	    {
		char *nameWithoutSpace = (char *) malloc(sizeof(char) * 18);
		strcpy(nameWithoutSpace, q->data->name);
		if(strcmp(rtrimHOTFAT(nameWithoutSpace, ' '),".") && strcmp(rtrimHOTFAT(nameWithoutSpace, ' '),".."))
		{
		    free(nameWithoutSpace);
		    pthread_mutex_unlock(&(dir->data->dir_mutex));
		    return -ENOENT;
		}
		free(nameWithoutSpace);
		q = q->sgt;
	    }
	    
	    char *dirFat = (char *) malloc(sizeof(char)*33);
	    char *fatherPath = (char *) malloc(sizeof(char)*257);
	    directory *fatherDirectory;// =  (directory *) malloc(sizeof(directory));
	    
	    fatherName(path,fatherPath);
	    searchDirectory(fatherPath,root,&fatherDirectory);
	    free(fatherPath);
	    
	    if(strcmp(dir->data->longName, "null"))
	    {
		char *dirLongName = (char *) malloc(sizeof(char)*33);
		createLongNameInput(&dirLongName, dir->data);
		pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirLongName,4);
		pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
		free(dirLongName);
	    }
	    
	    createDirectoryInput(&dirFat,dir->data);
	    pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
	    saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
	    pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
	    free(dirFat);
	    
	    if(!getDirectory(path,root,&dir))
	    {
		pthread_mutex_unlock(&(dir->data->dir_mutex));
		return -ENOENT;
	    }
	    else
	    {
		pthread_mutex_unlock(&(dir->data->dir_mutex));
		pthread_mutex_destroy(&(dir->data->dir_mutex));
		free(dir->data);
		free(dir);
	    }
	}
	else
	{
	    pthread_mutex_unlock(&(dir->data->dir_mutex));
	    return -ENOENT;
	}
	return 0;
}

int hotfat_unlink(const char* path)
{
	directory *dir = (directory *) malloc(sizeof(directory));
	
	searchDirectory(path,root,&dir);
	
	if(dir->content == NULL)
	{
		enum cluster_state state;
		unsigned int cluster_num, aux_cluster_num;
		
		if(dir->data->idCluster != 0)
		{
		    cluster_num = dir->data->idCluster;
		    do
		    {
			getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
			setFreeCluster(freeClusters, cluster_num);
			cluster_num = aux_cluster_num;
			
		    } while(state == used);
		}
		
	    
		char *dirFat = (char *) malloc(sizeof(char)*33);
		char *fatherPath = (char *) malloc(sizeof(char)*257);
		directory *fatherDirectory;// =  (directory *) malloc(sizeof(directory));
		
		fatherName(path,fatherPath);
		searchDirectory(fatherPath,root,&fatherDirectory);
		free(fatherPath);
		
		if(strcmp(dir->data->longName, "null"))
		{
		    char *dirLongName = (char *) malloc(sizeof(char)*33);
		    createLongNameInput(&dirLongName, dir->data);
		    pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		    saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirLongName,4);
		    pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
		    free(dirLongName);
		}
		
		createDirectoryInput(&dirFat,dir->data);
		pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
		pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
		free(dirFat);
		
		if(!getDirectory(path,root,&dir))
		    return -ENOENT;
		else
		{
		    free(dir->data);
		    free(dir);
		}
		
	}
	else
		return -ENOENT;

	return 0;
}

int hotfat_rename(const char *path, const char *newPath)
{
	char *name = (char *) malloc(sizeof(char) * 256);
	char *dirFat = (char *) malloc(sizeof(char)*33);
	char *fatherPath = (char *) malloc(sizeof(char)*256);
	directory *dir;// = (directory *) malloc(sizeof(directory));
	directory *fatherDirectory;// =  (directory *) malloc(sizeof(directory));
	directory *newDir;// = (directory *) malloc(sizeof(directory));
	
	if(searchDirectory(path,root,&newDir) == -ENOENT)
	{
		//Búsco el directorio y el del padre,, con el mio obtengo el dirfat(los 32) y con el del padre escrivo en la fat con el 345
		fatherName(path,fatherPath);
		searchDirectory(path,root,&dir);
		createDirectoryInput(&dirFat,dir->data);
		searchDirectory(fatherPath,root,&fatherDirectory);
		pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,3);
		pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
		
		
		//Búsco el directorio viejo y lo quito
		directory *oldDir= (directory *) malloc(sizeof(directory));
		getDirectory(path,root,&oldDir);
		//Búsco el directorio padre del nuevo directorio
		newDir = (directory *) malloc(sizeof(directory));
		fatherName(newPath,fatherPath);
		searchDirectory(fatherPath,root,&newDir);
		
		//Agrego el nuevo directorio con el nuevo nombre
		newName(newPath,name);
		strcpy(oldDir->data->name,name);
		if(newDir->content == NULL)
			newDir->content = (directory *) malloc(sizeof(directory));
		addToListWithSublist((glws *)newDir->content,oldDir->data,(glws *)oldDir->content);
		
		
		createDirectoryInput(&dirFat,oldDir->data);
		searchDirectory(fatherPath,root,&fatherDirectory);
		pthread_mutex_lock(&(fatherDirectory->data->dir_mutex));
		saveDirectoryInputIntoLinkedClusters(fatherDirectory->data->idCluster,dirFat,1);
		pthread_mutex_unlock(&(fatherDirectory->data->dir_mutex));
	}
	else
	{
	    free(name);
	    free(dirFat);
	    free(fatherPath);
		return -EEXIST;
	}

    free(name);
    free(dirFat);
    free(fatherPath);
	
    return 0;
}

int hotfat_getattr(const char *path, struct stat *stbuf)
{
    int res = 0, aux_size = 0;
    
    if(strncmp(path,"/.Trash",7) != 0 && strcmp(path,"/.hidden") != 0 && strncmp(path,"/.xdg-volume",11) != 0 && strncmp(path,"/autorun.inf",11) != 0 && strncmp(path,"/.directory",10) != 0){

        if(strcmp(path, "/") == 0)
		{
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
		}   	 
		else
		{
			directory *q;// = (directory *) malloc(sizeof(directory));
			searchDirectory(path,root,&q);
			if(q!=NULL && q->data!=NULL)
				getAttrOfDir(q,path,stbuf);
			else 
				return -ENOENT;

		}
    }
    
    return 0;
}

int hotfat_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
	filler(buf,".",NULL,0);
	filler(buf,"..",NULL,0);
	directory *q = root->content;
	if(strcmp(path, "/") != 0)
	{

		directory *dir = (directory *) malloc(sizeof(directory));
		searchDirectory(path,root,&dir);
		if(dir == NULL)
		    return -ENOENT;
		q = dir->content;
	}
	while(q!=NULL && q->data != NULL)
	{
		youMakeMeFiller(q,buf,&filler);
		q = q->sgt;
	}

	return 0;
}


int readSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char **data_sector, int iSocketConectado)
{
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int) + 1);
    InfoIPC sInfoIPC;
    memset(num_sector_str, '\0', sizeof(char) * sizeof(unsigned int) + 1);
    sprintf(num_sector_str, "%u", num_sector);
    sInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
    generarStructIPC(num_sector_str,READ_SECTOR_REQUEST,&sInfoIPC);
    enviarIPC(iSocketConectado ,&sInfoIPC);
    free(num_sector_str);
    free(sInfoIPC.payload);
    
    InfoIPC rInfoIPC;
    unsigned int nro_pedido, nro_sector;
//     recibirIPC(iSocketConectado,&rInfoIPC);
//     if(rInfoIPC.payLoadDescriptor == NUMEROPEDIDO)
//     {
// 	nro_pedido = atoi(rInfoIPC.payload);
    
	recibirIPC(iSocketConectado,&rInfoIPC);
	if(rInfoIPC.payLoadDescriptor == RTA_READ_SECTOR_REQUEST)
	{
	    nro_sector = atoi(rInfoIPC.payload);
    	    free(rInfoIPC.payload);
	    recibirIPC(iSocketConectado,&rInfoIPC);
	    memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
    	    free(rInfoIPC.payload);
	}
//     }
    
//     InfoIPC rInfoIPC;
//     char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
//     
//     sprintf(num_sector_str, "%u", num_sector);
//     rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
//     generarStructIPC(num_sector_str,READ_SECTOR_REQUEST,&rInfoIPC);
//     enviarIPC(iSocketConectado,&rInfoIPC);
//     
//     recibirIPC(iSocketConectado,&rInfoIPC);
//     memcpy(*data_sector, rInfoIPC.payload, rInfoIPC.payLoadLength);
//     
//     free(rInfoIPC.payload);
//     free(num_sector_str);


    return 1;
}


int writeSectorFAT(FILE* disk, bootRegion *boot, unsigned int num_sector, unsigned int offset, unsigned int size, char *data_sector, int iSocketConectado)
{
    InfoIPC rInfoIPC;
    char *num_sector_str = (char *) malloc(sizeof(char) * sizeof(unsigned int)+ 1);
    
    char *data_send = (char *) malloc(sizeof(char) * size);
    sprintf(num_sector_str, "%u", num_sector);
    rInfoIPC.payLoadLength = strlen(num_sector_str) + 1;
    generarStructIPC(num_sector_str,WRITE_SECTOR_REQUEST,&rInfoIPC);
    enviarIPC(iSocketConectado,&rInfoIPC);
    free(rInfoIPC.payload);
    
//     recibirIPC(iSocketConectado,&rInfoIPC);
//     if(rInfoIPC.payLoadDescriptor == RTA_WRITE_SECTOR_REQUEST)
//     {
	rInfoIPC.payLoadLength = 512;
	memcpy(data_send, data_sector + offset, size);
	generarStructIPC(data_send,SET_SECTORES,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
   	free(rInfoIPC.payload);
	
	recibirIPC(iSocketConectado,&rInfoIPC);
    	free(rInfoIPC.payload);
// 	if(rInfoIPC.payLoadDescriptor != RTA_SET_SECTORES)
// 	{
// 	    close(iSocketConectado);
// 	    free(rInfoIPC.payload);
// 	    free(num_sector_str);
// 	    free(data_send);
// 	    return -1;
// 	}
//     else
// 	return -1;
    
//     }
    
    free(num_sector_str);
    free(data_send);
    
    return 1;
    
}


int fsinfo()
{
		
    printf("\n--- HOTFAT's FileSystem Info ---\n\n");

    unsigned int i, clusters_free = 0, clusters_used = 0;

    while(clusters_loaded_FAT < boot->count_clusters_fat)
	loadFAT(disk, boot, fatTablePointer);
    
    for(i=0; i < clusters_loaded_FAT; i++)
    {
	if(freeClusters[i] == '0')
	    clusters_free++;
	else
	    clusters_used++;
    }

    printf("Cantidad de clusters ocupados: %u\n", clusters_used);
    printf("Cantidad de clusters libres: %u\n", clusters_free);
    printf("Tamaño de un sector: %u B\n", boot->bytes_per_sector);
    printf("Tamaño de un cluster: %u B\n", boot->cluster_size);
    printf("Tamaño de la tabla FAT: %u KB\n", (boot->count_clusters_fat * boot->cluster_size) / 1024 );

    printf("\n--------------------------------\n\n");

    return 1;
}

int finfo(const char *path)
{
    unsigned int cluster_num, aux_cluster_num, cont;
    enum cluster_state state;
    directory *dir = (directory *) malloc (sizeof(directory));
    
    searchDirectory(path, root, &dir);
    if(dir != NULL)
    {	
	if(dir->data->idCluster > 0)
	{
	    printf("\n------ HOTFAT's File Info ------\n");
	    printf("-- Archivo: %s\n", path);
	    printf("#Clusters:\n[");
	    
	    cluster_num = dir->data->idCluster;
	    printf("%u", cluster_num);
	    getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
	    
	    cluster_num = aux_cluster_num;
	    cont = 1;
	    while((state == used) && (cont < 20))
	    {
		printf(",%u", cluster_num);
		getClusterState(fatTablePointer, cluster_num, &state, &aux_cluster_num);
		cluster_num = aux_cluster_num;
		cont++;
	    }
	    printf("]\n");
	}
	else
	    printf("El archivo está vacío.\n");
    }
    else
	printf("El archivo no existe.\n");
    printf("\n--------------------------------\n\n");
    
    return 1;
}


int readSector2(char * numero){
	

	char buf[512];
	int iSocketConectado;
	InfoIPC rInfoIPC;
	
	/*HANDSHAKE*/ 	
	iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado, ipDisco,puertoDisco);	
	rInfoIPC.payLoadLength=5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	recibirIPC(iSocketConectado,&rInfoIPC);
	
	
	
	if(rInfoIPC.payLoadDescriptor== HSOK){
		
		
		rInfoIPC.payLoadLength=strlen(numero)+1;
		generarStructIPC(numero,READ_SECTOR_REQUEST,&rInfoIPC);
		enviarIPC(iSocketConectado,&rInfoIPC);
		
		InfoIPC rInfoIPC2;
		/*Recibo la data respondida*/
		
		memset(buf,'\0',512);
		recibirIPC(iSocketConectado,&rInfoIPC2);
		memcpy(buf,rInfoIPC2.payload,512);

		
		/*Ver como cerrar bien el socket*/
		close(iSocketConectado);
		
	}
	
	return 0;
}

int readSector3(int numero, sectors *listSectors){
	
	
	char sContador[20];
	int iSocketConectado;
	InfoIPC rInfoIPC;
	int contador=0;
	fd_set set_socketsHiloPrincipal;
	cliente *pNodoCliente,*pAuxCliente;
	int iMayorSocket;
	cliente* ListaClientes=NULL;
	cliente* ListaClientes_Ult=NULL;
	
	/*Creo 8 socketes y envio lecturas de 8 numeros*/
	
	while(contador!=8){	
		
		/*HANDSHAKE*/ 	
		int iSocketConectado = crearSocket(AF_INET);
		Conectar2(iSocketConectado,ipDisco,puertoDisco);	
		rInfoIPC.payLoadLength=5;
		generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
		enviarIPC(iSocketConectado,&rInfoIPC);
		recibirIPC(iSocketConectado,&rInfoIPC);
		
		if(rInfoIPC.payLoadDescriptor== HSOK){
		
			pNodoCliente = (cliente *)malloc(sizeof(cliente));
			pNodoCliente->socketCliente=iSocketConectado;
			agregarAListaDeClientes(&pNodoCliente,&ListaClientes,&ListaClientes_Ult);
			intacad((contador+numero),sContador);
			rInfoIPC.payLoadLength=strlen(sContador)+1;
			generarStructIPC(sContador,READ_SECTOR_REQUEST_LAST,&rInfoIPC);
			enviarIPC(iSocketConectado,&rInfoIPC);
		}	
		
		contador++;
	}
	
	/*Escucho respuestas en esos sockets*/
	
	while(ListaClientes!=NULL){
	
		
		
		FD_ZERO(&set_socketsHiloPrincipal);
		pAuxCliente = ListaClientes;
		while(pAuxCliente != NULL)
		{
			FD_SET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal);	
			if(pAuxCliente->socketCliente > iMayorSocket)
				iMayorSocket = pAuxCliente->socketCliente;
			pAuxCliente = pAuxCliente->Sgt;
		}
		
		
		select(iMayorSocket + 1,&set_socketsHiloPrincipal, NULL, NULL,NULL);
		
		pAuxCliente = ListaClientes;
		while(pAuxCliente != NULL)
		{
			if( FD_ISSET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal ) > 0 ){
				break;
			}
			pAuxCliente = pAuxCliente->Sgt;
		}
		if(pAuxCliente != NULL)
		{		
			recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
			printf("Sector: %s \n",(char *)rInfoIPC.payload);
			recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
			printf("Recibi datos: %s \n",(char *)rInfoIPC.payload);
			close(pAuxCliente->socketCliente);
			FD_CLR(pAuxCliente->socketCliente, &set_socketsHiloPrincipal);
			SacarDeLista_Clientes(&pAuxCliente,&ListaClientes,&ListaClientes_Ult);
			free(pAuxCliente);
			
			sector *aux_sec = (sector *) malloc (sizeof(sector));
			aux_sec->sec = (char *) malloc(sizeof(char) * boot->bytes_per_sector);
			memcpy(aux_sec->sec, rInfoIPC.payload , 512);
			addToList((gl *)listSectors,aux_sec);
			
		}

	}
	
	return 0;
}
	


int writeSector3(int numero, sectors *listSectors){	
	
	
	char sContador[20];
	int iSocketConectado;
	InfoIPC rInfoIPC;
	int contador=0;
	fd_set set_socketsHiloPrincipal;
	cliente *pNodoCliente,*pAuxCliente;
	int iMayorSocket;
	cliente* ListaClientes=NULL;
	cliente* ListaClientes_Ult=NULL;

	
	
	/*Creo 8 socketes y envio escrituras de 8 numeros*/
	
	sectors *q = listSectors;
	
	while(contador!=8){	
		
		q = listSectors;
		
		/*HANDSHAKE*/ 	
		iSocketConectado = crearSocket(AF_INET);
		Conectar2(iSocketConectado,ipDisco,puertoDisco);	
		rInfoIPC.payLoadLength=5;
		generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
		enviarIPC(iSocketConectado,&rInfoIPC);
		recibirIPC(iSocketConectado,&rInfoIPC);
		
		if(rInfoIPC.payLoadDescriptor== HSOK){
		
			pNodoCliente = (cliente *)malloc(sizeof(cliente));
			pNodoCliente->socketCliente=iSocketConectado;
			agregarAListaDeClientes(&pNodoCliente,&ListaClientes,&ListaClientes_Ult);
			
			intacad((contador*numero),sContador);
			rInfoIPC.payLoadLength=strlen(sContador)+1;
			generarStructIPC(sContador,WRITE_SECTOR_REQUEST,&rInfoIPC);
			enviarIPC(iSocketConectado,&rInfoIPC);
		
			rInfoIPC.payLoadLength=512;
			generarStructIPC(q->data->sec,WRITE_SECTOR_REQUEST,&rInfoIPC);
			enviarIPC(iSocketConectado,&rInfoIPC);
			
			
			
		}
		
		listSectors = listSectors->sgt;
		free(q->data->sec);
		free(q->data);
		free(q);
		
		contador++;
	}
	
	/*Escucho respuestas en esos sockets*/
	
	while(ListaClientes!=NULL){
	
		
		FD_ZERO(&set_socketsHiloPrincipal);
		pAuxCliente = ListaClientes;
		while(pAuxCliente != NULL)
		{
			FD_SET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal);	
			if(pAuxCliente->socketCliente > iMayorSocket)
				iMayorSocket = pAuxCliente->socketCliente;
			pAuxCliente = pAuxCliente->Sgt;
		}
		
		
		select(iMayorSocket + 1,&set_socketsHiloPrincipal, NULL, NULL,NULL);
		
		pAuxCliente = ListaClientes;
		while(pAuxCliente != NULL)
		{
			if( FD_ISSET(pAuxCliente->socketCliente , &set_socketsHiloPrincipal ) > 0 ){
				break;
			}
			pAuxCliente = pAuxCliente->Sgt;
		}
		if(pAuxCliente != NULL)
		{		
			recibirIPC(pAuxCliente->socketCliente,&rInfoIPC);
			printf("Recibi confirmacion de escritura de sector: %s \n",(char *)rInfoIPC.payload);
			/*Se desconecta cliente*/
			close(pAuxCliente->socketCliente);
			FD_CLR(pAuxCliente->socketCliente, &set_socketsHiloPrincipal);
			SacarDeLista_Clientes(&pAuxCliente,&ListaClientes,&ListaClientes_Ult);
			free(pAuxCliente);
			
		}

	}
	
	return 0;
}
	


int writeSector2(char * numero){
	
	int iSocketConectado;
	InfoIPC rInfoIPC;
	
	
	/*HANDSHAKE*/ 	
	iSocketConectado = crearSocket(AF_INET);
	Conectar2(iSocketConectado,ipDisco,puertoDisco);	
	rInfoIPC.payLoadLength=5;
	generarStructIPC("nada",HANDSHAKE,&rInfoIPC);
	enviarIPC(iSocketConectado,&rInfoIPC);
	recibirIPC(iSocketConectado,&rInfoIPC);
	
		
	if(rInfoIPC.payLoadDescriptor== HSOK){
		
		/*Envio el numero del sector*/
		rInfoIPC.payLoadLength=strlen(numero)+1;
		generarStructIPC(numero,WRITE_SECTOR_REQUEST,&rInfoIPC);
		enviarIPC(iSocketConectado,&rInfoIPC);
		
		/*Envio los datos a escribir en el sector*/
		rInfoIPC.payLoadLength=strlen(numero)+1;
		generarStructIPC(numero,WRITE_SECTOR_REQUEST,&rInfoIPC);
		enviarIPC(iSocketConectado,&rInfoIPC);
		
	
		/*Recibo el numero de sector respondido*/
		recibirIPC(iSocketConectado,&rInfoIPC);
		printf("%s=%s \n",numero,(char *)rInfoIPC.payload);
		
		
		/*Ver como cerrar bien el socket*/
		close(iSocketConectado);
		
	}
		
	return 0;
}


void intacad ( int n , char* cadena)
{	
    int j=0;
    int i=0;
	char aux;

	do
    {
		cadena[i] = (n % 10) + '0';    
		n=n/10;
		i++;
	}while (n > 0);

    cadena[i] = '\0';
    i--;

	while(i>j)
	{
		aux=cadena[i];
		cadena[i]=cadena[j];
		cadena[j]=aux;
		i--;
		j++;
	}

}


int ordenarLista(readNipcSectors **lista)
{ 
    readNipcSectors *primero, *segundo, *tercero, *temp; 
    
    if(*lista != NULL && (*lista)->data != NULL)
    { 
	primero = *lista; 
// 	printf("Primero no nulo %i \n", primero->data->sector_num); 
	
	if(primero->sgt != NULL)
	{
	    segundo = primero->sgt;
// 	    printf("Segundo no nulo %i \n", segundo->data->sector_num); 
    
	    if (primero->data->sector_num > segundo->data->sector_num) 
	    { 
		*lista = segundo; 
		primero->sgt = segundo->sgt; 
		segundo->sgt = primero; 
		
		return 0;
	    }
	    
	    if(segundo->sgt != NULL)
	    {
// 		printf("Tercero no nulo %i \n", segundo->data->sector_num); 
		tercero = segundo->sgt; 
	
		while(tercero != NULL)
		{
		    if (segundo->data->sector_num > tercero->data->sector_num) 
		    { 
			primero->sgt = tercero; 
			segundo->sgt = tercero->sgt; 
			tercero->sgt = segundo;

			return 0;
		    } 
		    
		    primero = segundo; 
		    segundo = tercero; 
		    tercero = tercero->sgt; 
			
		}
		return 1;
	    }
	    return 1;
	}
	return 1;
    }
    else
    { 
	printf("\nLa cola esta vacia.\n"); 
	return 1;
    } 
    
    return 0;
} 

static void * console_run(void *param)
{
  int chChoice;
  char szTemp[256];
  char path[257];
  int eStatus = 1;

  while(eStatus)
  {
    fprintf(stdout, "\n------- HOTFAT's FILE SYSTEM --------\n");
    fprintf(stdout, "\n-------------- Console --------------\n"
                    "\n(I)nfo file system, (F)ile info, (Q)uit"
                    "\nEnter Command : ");
    chChoice = getchar();
    fgets(szTemp, sizeof(szTemp), stdin);

    switch (tolower(chChoice)) {
      case 'i':
        fsinfo();
        break;

      case 'f':
	fprintf(stdout,"\nEnter Test Name : ");
	fgets(path, 257, stdin);
	finfo(path);
        break;
	
      case 'q':
        eStatus = 0;
        break;
	
	
      /* To stop gcc from cribbing */
      default:
        break;
    }
  }
}

